-3

I have a folder with 20000 files in it. I need to split it into subfolders with increasing directory name (dir_1, dir_2....) with each folder having 500 files each in such a way that for example if files are from file_1.png to file_20000, the first folder should contain first 500 files i.e., file_1 to file 500 and immediate folder should contain files in a continued manner i.e, file_501 to file_1000 and so on. enter image description here

Rui F Ribeiro
  • 55,929
  • 26
  • 146
  • 227
Praveen Kumar
  • 69
  • 2
  • 6
  • 5
    please _please_ do not post images of text. Or, if you must, at least don't post such sparse images, and make them more helpful in the context of the question. – DopeGhoti Jan 07 '19 at 18:15

3 Answers3

3
#!/bin/sh

files_per_dir=500

set -- file_*

printf 'There are %d files\n' "$#"
printf 'Putting %d files in each new directory\n' "$files_per_dir"

N=0 # directory counter
n=0 # file counter

for filename do

    if [ "$(( n % files_per_dir ))" -eq 0 ]; then
        N=$(( N + 1 ))
        dir="dir_$N"
        printf 'Creating directory %s\n' "$dir"
        # mkdir "$dir"
    fi

    n=$(( n + 1 ))

    printf 'Moving %s to %s\n' "$filename" "$dir"
    # mv -i -- "$filename" "$dir"

done

The above would put 500 files into each directory (the actual commands that changes things have been commented out for safety). The filenames are assumed to match file_* and each new directory will be called dir_N where N is a positive integer.

If you want to move the files based on their numerical names (the above sorts the files in lexicographical order), then use

printf 'Moving %s to %s\n' "file_$n" "$dir"
# mv -i -- "file_$n" "$dir"

instead (i.e. replace the corresponding two lines in the first script with these, in this order).


Shortened version:

#!/bin/sh

files_per_dir=500

set -- file_*

n=0

for filename do
    n=$(( n + 1 ))

    N=$(( (n/files_per_dir) + 1 ))
    [ ! -d "dir_$N" ] && mkdir "dir_$N"

    # mv -i -- "$filename" "dir_$N"
    # or...
    # mv -i -- "file_$n" "dir_$N"
done
Kusalananda
  • 320,670
  • 36
  • 633
  • 936
0
cd lotsafiles
for i in {1..20000}; do
  dirnum="$(((i/500)+1))"
  mkdir -p "dir_${dirnum}" # using -p allows this to be less noisy on repeat runs
  mv "file${i}.png" "dir_${dirnum}"/
done
DopeGhoti
  • 73,792
  • 8
  • 97
  • 133
-1

Something simple along the lines of:

#!/bin/bash
typeset -i i
typeset -i j
typeset -i k

i=0
j=0
k=0
mkdir dir_$j
for file in * ; do
   i=$i+1
   k=$k+1
   if [ $i = 500 ] ; then
       j=$j+1
       i=0
       mkdir  dir_$j
   fi
   mv "$file" dir_$j/file_$k
done

Not tested, so you might put an echo in front of the mv "$file" dir_$j to see if it does what you want. Anyway it will give you an idea of how to do what you want.

Ljm Dullaart
  • 4,142
  • 11
  • 26
  • Yes it works. That's why the `typeset -i` is there. Yes, I use string comparison, but that also works. Would you prefer I put `#!/bin/sh` as first line? – Ljm Dullaart Jan 07 '19 at 18:23
  • 1
    Using the string comparison operator for `test` (`=`) for numerical comparisons is bad practice. Use the numerical comparisons (`-eq`) when performing numerical equality tests. Using the wildard (`for file in *`) may catch more files than the specified `file_{1..20000}.png`. – DopeGhoti Jan 07 '19 at 18:32