Basic tip today, this time for sifting through a directory tree and plucking out files that match a certain filter.
I needed to move some of the office photo collection off CD and USB into a different location to sort them manually. A lot of international characters and intermingled, unwanted files were complicating things.
I’m sure there are lots of ways to do this, but this is what I did.
find /media/ -iname "*jpg" -exec cp '{}' /home/kmandla/hold/ \;
Obviously you can change that to move the files, or anything else you like.
The regular cp
command — or as I was trying to use it, cp -Rv /media/*jpg /home/kmandla/hold
— wasn’t working with me, and my variations on that line were likewise failures.
find
did the job right the first time. And was quicker than pointing and clicking, that’s for sure.
My approach would have been just ‘cp -Rv /media/**/*jpg /destination’.
/media/*jpg only substitutes files that are directly inside /media. I use zsh, but it worked with bash too.
On the other note, I should try to learn more about ‘find’. So far, it rarely behaved the way I anticipated =)
For some reason, I have never found the Find command particularly easy to learn, and I’ve used the GNU and BSD versions of the command. It’s probably because I need the command so infrequently.
For the ** to work in bash, you first need: shopt -s globstar
I use a similar command:
find /pathtoinputdir/ -name “*.*” -type f -exec cp -urvp ‘{}’ /pathtooutputdir \;
Two more comments on the find syntax:
– The {} don’t need quoting
– With GNU find you can replace the \; with + to pass many filenames to one cp command opposed to fork()ing a cp for each file
Also “*.*” is unnecessary (reminds me of DOS syntax), “*” will do.
Actually, “*.*” and “*” are different. “*.*” only matches files with a dot in the name. And, if you are going to do -name “*”, you may as well leave the -name predicate out all together:
find /pathtoinputdir -type f -exec cp -urvp {} \;