In some cases, you could face issues copying .MYD and .MYIs because of a major weakness MyISAM has: Data changes (changes to .MYD files) are cached in the OS. (Of course, this would be 100 times worse with MySQL in Windows, so I'll leave Windows out of this answer).
If you are using MySQL 5.6, I have a little good news.
The command FLUSH TABLES WITH READ LOCK would look all MyISAM tables under a single lock. MySQL 5.6 now has the syntax FLUSH TABLES db.tb,db.tb ... WITH READ LOCK.
The MySQL 5.6 Documentation says
FLUSH TABLES tbl_name [, tbl_name] ... WITH READ LOCK
This statement flushes and acquires read locks for the named tables.
The statement first acquires exclusive metadata locks for the tables,
so it waits for transactions that have those tables open to complete.
Then the statement flushes the tables from the table cache, reopens
the tables, acquires table locks (like LOCK TABLES ... READ), and
downgrades the metadata locks from exclusive to shared. After the
statement acquires locks and downgrades the metadata locks, other
sessions can read but not modify the tables.
Because this statement acquires table locks, you must have the LOCK
TABLES privilege for each table, in addition to the RELOAD privilege
that is required to use any FLUSH statement.
This statement applies only to existing base tables. If a name refers
to a base table, that table is used. If it refers to a TEMPORARY
table, it is ignored. If a name applies to a view, an ER_WRONG_OBJECT
error occurs. Otherwise, an ER_NO_SUCH_TABLE error occurs.
Use UNLOCK TABLES to release the locks, LOCK TABLES to release the
locks and acquire other locks, or START TRANSACTION to release the
locks and begin a new transaction.
This variant of FLUSH enables tables to be flushed and locked in a
single operation. It provides a workaround for the restriction in
MySQL 5.6 that FLUSH TABLES is not permitted when there is an active
LOCK TABLES ... READ.
This statement does not perform an implicit UNLOCK TABLES, so an error
results if you use the statement while there is any active LOCK TABLES
or use it a second time without first releasing the locks acquired.
If a flushed table was opened with HANDLER, the handler is implicitly
flushed and loses its position.
CAVEAT : For you InnoDB people, same doc has FLUSH TABLES tbl_name [, tbl_name] ... FOR EXPORT that include metadata locking within the system tables.
You could write a script to lock every MyISAM table in a database, sleep that DB Connection, do your OS copy, and release the lock.
This is what I do now because I work with a MyISAM table that has 4019 partitions. This forces the flush of everything for .MYDs. Issuing a lock like this and sleeping the connection, I can then FTP MYDs and MYI to other data centers.
If you use Percona Server 5.6, I have better news. Percona just invented LOCK TABLES FOR BACKUP. This takes the guess work and grunt work out of locking tables with a measure of confidence in the tables' consistency.
http://www.percona.com/doc/percona-server/5.6/management/backup_locks.html
YOUR ACTUAL QUESTION
You should make the effort to script the locking of MyISAM per database.
Here is the script I use to create a lock on every MyISAM table in a database before the backup
MYSQL_HOSTADDR=${1}
DB_SUFFIX=${2}
RUNLOG=${3}
MYSQL_DATABASE=DB_${DB_SUFFIX}
MYSQL_CONN="-h${MYSQL_HOSTADDR} -D${MYSQL_DATABASE}"
PRODUCT_LIST="prod1 prod2 prod3"
#
# Acquire Locks
#
for PRODUCT in `echo "${PRODUCT_LIST}"`
do
PREFIX=sum_${PRODUCT}
LOCK_SLEEP_KILL_SCRIPT=/tmp/Kill_Summary_Table_Locks_For_${PRODUCT}_${DB_SUFFIX}.sql
SQL="SELECT GROUP_CONCAT(table_name) FROM information_schema.tables"
SQL="${SQL} WHERE table_schema=DATABASE() AND table_name LIKE '${PREFIX}%'"
TABLES_TO_LOCK=`mysql -h${MYSQL_HOSTADDR} -D${MYSQL_DATABASE} -ANe"${SQL}"`
LOCK_PATTERN="LockProcessFor${PRODUCT}"
FLUSH_COMMAND="FLUSH TABLES ${TABLES_TO_LOCK} WITH READ LOCK; SELECT SLEEP(86400) INTO @${LOCK_PATTERN}"
mysql ${MYSQL_CONN} -ANe"${FLUSH_COMMAND}" &
SQL="SELECT MAX(id) FROM (SELECT 0 id UNION"
SQL="${SQL} SELECT id FROM information_schema.processlist"
SQL="${SQL} WHERE LOCATE('${LOCK_PATTERN}',Info)>0"
SQL="${SQL} AND id <> CONNECTION_ID()) A"
SLEEP_ID=0
while [ ${SLEEP_ID} -eq 0 ]
do
sleep 5
SLEEP_ID=`mysql -h${MYSQL_HOSTADDR} -ANe"${SQL}"`
done
echo "KILL QUERY ${SLEEP_ID};" > ${LOCK_SLEEP_KILL_SCRIPT}
done
Here is the script I use to release those locks after the backup
MYSQL_HOSTADDR=${1}
cd /tmp
ls Kill_Summary_Table_Locks_For*.sql > KillScriptList.txt
for KILLSQL in `cat KillScriptList.txt` ; do mysql -h${MYSQL_HOSTADDR} < ${KILLSQL} ; rm -f ${KILLSQL}; done
Give it a Try !!!