A "simple" find / xargs will do:
find -maxdepth 1 -type f -print0 | xargs -r -0 -P0 -n 500 sh -c 'mkdir newdir.$$; mv " $@ " newdir.$$/' xx
Explanation:
- to find
-maxdepth 1
prevents the search from recursively traversing any directories, security is not required if you know that you do not have directories.-type f
find files-print0
separate files with null char instead of LF (to handle strange names)
- xargs
-r
do not start with an empty argument list-0
read files separated by zero-P0
create as many processes as you need-n 500
start each process with 500 arguments
- w
-c
execute script command line as next argumentmkdir newdir.$$
create a new directory ending with the shell PID process.mv " $@ " newdir.$$/
move the script arguments (each one is quoted) to the newly created directoryxx
name for the command line provided that the script (see sh manual)
Please note that this is not what I will use in the production process, this is mainly due to the fact that $$
(pid) will be different for each process executed by xargs
If you need sorted files, you can pull sort -z
between find xargs.
If you need more meaningful directory names, you can use something like this:
echo 1 >../seq find -maxdepth 1 -type f -print0 |sort -z | xargs -r -0 -P1 -n 500 sh -c 'read NR <../seq; mkdir newdir.$NR; mv " $@ " newdir.$NR/; expr $NR + 1 >../seq' xx
echo 1 > ../seq
write the first directory suffix in the file (make sure it is not in the current directory)-P1
tell -P1
to run one team at a time to prevent race conditions.read NR <../seq
read current directory suffix from fileexpr $NR + 1 >../seq
write the following directory suffix for the next runsort -z
sort files
Sorin source share