How do I segregate multiple files based on file size into a sub directory?
I have a bunch of video files which I would like to segregate based on file size I have decided.
Example:
Folder BB has 15 files of various file size.
I have sub folder set as:
less than 100 MB -- folder A
100 MB to 500 MB -- folder B
more than 500 MB -- folder C
So instead of manually doing it can it be done via Bash or a script.
I have a general idea that find
command and a proper if else would work, but have no idea how to script it.
Anyway, a general programming frame would be:
float _size=[file_size]; // Reads the file size
if(_size<100) // File size is less than 100 MB
{ exec mv [file] /A/* ; // Move to folder A }
else if(_size>500) // File size is greater than 500 MB
{ exec mv [file] /C/* ; // Move to folder C }
else if((_size<=500)||(_size>=100)) //file size is between 100 to 500
{ exec mv [file] /B/* ; // Move to folder C}
else
{print("file error");}
So I hope it is easy to do. The above was just a general idea I would have done.
I suggest to loop over all files in the current directory with this for
loop:
for i in *; do
size=$(stat --printf="%s" "$i")
if [ $size -lt 100000000 ]; then
mv "$i" A/
elif [ $size -lt 500000000 ]; then
mv "$i" B/
else
mv "$i" C/
fi
done
You requested Megabyte, if you actually wanted 100/500 Mebibyte use 104857600
and 524288000
accordingly.
If the directory contains other files and you just want to process e.g. .avi
files, use:
for i in *.avi; do …
Explanations
-
for i in *; do … ; done
– loop over all files in the current directory -
size=$(stat --printf="%s" "$i")
– get the file size in bytes usingstat
and save it as variablesize
-
if A; then B; elif C; then D; else E; fi
– if A is true do B, else if C is true do D, else do E -
[ $size -lt X ]
– test whethersize
isl
esst
han X -
mv "$i" Y/
– move the currently processed file inside folder Y
You can do this kind of thing with GNU find
e.g.
find BB/ -type f \( -size -100M -exec mv -t A/ {} + \
-o -size +500M -exec mv -t C/ {} + -o -exec mv -t B/ {} + \)
NOTES:
If you want to move files within the same tree (e.g.
A/
,B/
,C/
are subdirectories ofBB
) then you will need to preventfind
from recursing into these, using-maxdepth
or-prune
for example.Care is required due to the rounding behavior of
-size
. It's not a problem with this case, but for example-size -1M
will round all files smaller than 1024kB up to 1M such that only empty files match.
Testing with kilobyte sized files for convenience:
$ tree -h somepath/
somepath/
├── [ 0] file0
├── [100K] file100
├── [150K] file150
├── [200K] file200
├── [250K] file250
├── [300K] file300
├── [350K] file350
├── [400K] file400
├── [450K] file450
├── [ 50K] file50
├── [500K] file500
├── [550K] file550
└── [600K] file600
0 directories, 13 files
then
$ find somepath/ -type f \( -size -100k -exec mv -vt A/ {} + \
> -o -size +500k -exec mv -vt C/ {} + -o -exec mv -vt B/ {} + \)
'somepath/file50' -> 'A/file50'
'somepath/file0' -> 'A/file0'
'somepath/file550' -> 'C/file550'
'somepath/file600' -> 'C/file600'
'somepath/file250' -> 'B/file250'
'somepath/file200' -> 'B/file200'
'somepath/file100' -> 'B/file100'
'somepath/file300' -> 'B/file300'
'somepath/file500' -> 'B/file500'
'somepath/file350' -> 'B/file350'
'somepath/file450' -> 'B/file450'
'somepath/file400' -> 'B/file400'
'somepath/file150' -> 'B/file150'
giving
$ tree -h A B C
A
├── [ 0] file0
└── [ 50K] file50
B
├── [100K] file100
├── [150K] file150
├── [200K] file200
├── [250K] file250
├── [300K] file300
├── [350K] file350
├── [400K] file400
├── [450K] file450
└── [500K] file500
C
├── [550K] file550
└── [600K] file600
0 directories, 13 files