There is indeed a race condition (one that wouldn't cause harm, though).
The *
is expanded on entry to the loop. If you run a second instance of this script simultaneously then it will probably do nothing because all files it tries to move have already been moved. If no files are created in the source directory during the moving operation then the error messages should be your biggest problem.
But in general this structure is a very bad idea. *
expands to a sorted list. AFAIK it is not possible to deactivate that. Obviously, the sorting alone is a nightmare with 400K files. See man bash
, section "Pathname Expansion":
After word splitting, unless the -f option has been set, bash scans each word for the characters *, ?, and [. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of file names matching the pattern.
Furthermore you should not run one mv
instance per file as you can move several files at once.
This is a better solution (in the GNU world):
find . -mindepth 1 -maxdepth 1 -exec mv --target-directory=DIRECTORY {} +