I have a folder full of 1000 (or more) files. I want to have a script that creates a numbered folder and then moves the first 20 files (ordered by name) into that folder. It should then do this for the other files, increasing the folder number by 1, until all the files are in folders.

I've tried the following command but it doesn't do a whole directory automatically and doesn't increment the folder number automatically:

for i in ${srcdir}/*; do
  [ $((N--)) = 0 ] && break
  cp -t "${dstdir}" -- "$i"

How can this be done using bash?

  • Suggestion: you should try to solve the question, and post your attempt. Commented Oct 18, 2013 at 0:52
  • @ChuckCottrill done! Thanks for the suggestion Commented Oct 19, 2013 at 10:07

2 Answers 2


This script takes two (optional) arguments, the directory to partition, and the parition size. Since you didn't say whether you only want to move files, or move everything, I assumed you meant files, so I used the find command.

A few comments,

  • Had you not specified shell, something like this is more easily done in perl, ruby, or python.
  • find with maxdepth 1 does only the directory
  • you can move the files anywhere, just change the folder naming
  • since find is used, you can add -name, -mtime, -ctime, etc.


path=${1:-"."} #directory to start
howmany=${2:-20} #partition size
pushd $path; #move there
part=1; #starting partition
LIST="/usr/bin/find -maxdepth 1 -type f" #move only files?
#LIST="ls" #move everything #be careful, $folder will get moved also :-)
count=`$LIST |/usr/bin/wc -l`; #count of files to move
while [ $count -gt 0 ]; do
    if [ ! -d $folder ]; then /usr/bin/mkdir -p $folder; fi
    /usr/bin/mv `$LIST |/usr/bin/sort |/usr/bin/head -$howmany` $folder/.
    count=`$LIST |/usr/bin/wc -l`; #are there more files?
    part=$(expr $part + 1)
popd $path

Here is a script to test with (I didn't have an extra 1000 files lying around),

for f in 0 1 2 3 4 5 6 7 8 9; do
  for g in 0 1 2 3 4 5 6 7 8 9; do
    for h in 0 1 2 3 4 5 6 7 8 9; do
        touch $f$g$h

Only one for loop should be enough when your filesName ending with corresponding numbers but the shell is zsh.

for N in {0..800..20}: do
    mkdir "dir$N"
    mv "files{$N..$((N+19))}" "/path/to/dir$N/"

If it's in bash, then:

for N in {0..800..20}: do
    mkdir "dir$N"
    eval mv "files{$N..$((N+19))}" "/path/to/dir$N/"

Learning post: How can I use $variable in a shell brace expansion of a sequence?

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .