5

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:

  1. less than 100 MB -- folder A
  2. 100 MB to 500 MB -- folder B
  3. 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.

7

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 using stat and save it as variable size
  • 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 whether size is less than X
  • mv "$i" Y/ – move the currently processed file inside folder Y
  • can you just mention #1. which syntax is used to read the file size ? , #2. Linux would show the file size in bits or bytes ? – SIDDHARTH Oct 7 '17 at 15:52
  • 1
    @SIDDHARTH I'll add full explanations later, but for now: The output of stat --printf="%s" "$i" (where variable i holds the processed filename) is saved as variable size, stat prints lots of file information and the output can be controled with the --printf option, %s stands for “total size, in bytes” here. See man stat. – dessert Oct 7 '17 at 16:00
7

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 of BB) then you will need to prevent find 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
  • Just awesome, thank you for sharing! However as OP requests MB and (I suppose) has powers of 1000 in mind, is it right to use -size -100000000c (that's 100,000,000) for that? Btw tree has a --sort=size option. – dessert Oct 7 '17 at 18:57
  • @dessert yes they could use any of the suffixes listed in man find to get the exact sizes required – steeldriver Oct 7 '17 at 23:20
  • This is just another way to do that. This proves that there are multiple approach and ways to do the same things. As I previously mentioned,I had an idea that a proper script with find command and if-else would work supports my point of view. Thanks to both steeldriver and @dessert to help me code the script. – SIDDHARTH Oct 8 '17 at 8:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.