How to move all files with fewer than 5 bytes in BASH?
Asked Answered
G

4

9

I have a folder containing many audio files, but some are ~4 bytes and seem to contain nothing, they are 0 seconds long and have no sound. I want to move them to a folder called "temp/".

How can I move all of the files in the folder that have fewer than 5 bytes to this folder?

Groyne answered 16/11, 2013 at 3:16 Comment(0)
M
26

Find!

You can use find to do this for you:

find . -type f -maxdepth 1 -size -5c -exec mv {} temp/ \;

Explanation

-size -5c grabs all the files less than 5 bytes. The - indicates less than and the c indicates bytes.

-maxdepth 1 prevents you from trying to move the files on top of themselves when it tries to recurse into temp/ (after moving your initial files).

-exec mv {} temp/ \; simply runs mv on each file to put them in temp (the {} is substituted for the name of the file). The escaped semicolon marks the end of the mv command for exec.

There are other sizes available as well:

`b'    for  512-byte blocks (this is the default if no suffix is
       used)
`c'    for bytes
`w'    for two-byte words
`k'    for Kilobytes (units of 1024 bytes)
`M'    for Megabytes (units of 1048576 bytes)
`G'    for Gigabytes (units of 1073741824 bytes)
Mercantilism answered 16/11, 2013 at 3:32 Comment(2)
-maxdepth 1 is probably quite important, otherwise it would find the ones you've already moved!Hypostasize
@MatthewSchinckel Heh. That's what took me so long to answer originally. I was testing to make sure my find knowledge was working appropriately, kept getting 'x' and 'x' are the same file, then I realized it was recursing.Mercantilism
H
2

find -size 1c will give you all files that are exactly one byte.

As @user1666959 mentions, you can also use find . -type f -size -4c, which will find all files in the current directory (and subdirectories), that are 4 bytes and smaller.

$ find . -maxdepth 1 -type f -size -4c -exec mv {} temp/ \;

(Yes, you will need the trailing \;.

Note that find -size allows for other exact file size matches (such as 1k), but also allows you to search for files that take up the designated number of blocks on the disk (leaving off the unit).

$ man find

Provides a heap more info about how to use it to search.

Hypostasize answered 16/11, 2013 at 3:30 Comment(7)
What's wrong with doing it in one go? find . -type f -size -5c. The minus sign before the length argument says you want files of size less than 5.Strainer
Nice, that's much cleaner. The man page didn't mention you could do that!Hypostasize
Would this search skip directories?Iseabal
@Basilevs: Do you mean for if there are spaces in the matched filenames? (Oh, and the -type f should fix the other bit you mentioned).Hypostasize
Spaces are of no importance. What bothers me is that. {} are special substitution symbols in bashIseabal
Weird. All the docs for find typically let the {} just hang out there. Does it really have to be escaped @Basilevs?Mercantilism
I've never escaped {} in my find -exec stuff.Hypostasize
I
1
find . -maxdepth 1 -type f -size -5c -exec mv '{}' temp/ \;
Iseabal answered 16/11, 2013 at 3:34 Comment(0)
F
1

One solution would be:

find . -type f -maxdepth 1 | xargs du | sort -n |grep "^[0-5]\t"|sed "s/[0-5]//"|sed "s/^.//"|xargs -I ARG mv ARG temp/

It finds all files, lists their sizes, sorts by that, takes all that are size 0,1,2,3,4,5, gets just the filenames, and then runs the mv command on them!

Fornication answered 16/11, 2013 at 3:46 Comment(1)
Find has it's own switch for looking at file sizes.Hypostasize

© 2022 - 2024 — McMap. All rights reserved.