Updated: February 3, 2021
Behold, an interesting problem - or requirement, if you will. You have a folder full of images, say dozens or hundreds. And they are of different sizes, say height of 480 or 600 or 1024 pixels, and width of 200, 320 or 9000 pixels, and you would like to copy only high-quality, large-size images out of this folder into a separate location. Doing this manually can be a chore.
In this article, I'd like to show you a relatively simple command you can run in a terminal window, which will let you filter out your images by size, and then only copy those with an attribute that you like. Now, please be aware that there are dozens of different ways you can accomplish this, and my solution is no way unique or comprehensive (for every possible usecase), but it should do the trick just fine. Let's begin.
Tools of the trade
The only application you will need, in addition to the various default Linux command-line tools, is ImageMagick, which is a bundle/suite of image-processing utilities. It is installed in most distributions out of the box, so you won't need to do anything in most scenarios.
One-liner
Now, the command you need is this:
ls *.FFF | xargs -I{} identify -format '%i %w %h\n' {} | grep -w XXX | awk '{print $1}' | grep -v ^$ | xargs -I cp {} "destination folder"
What do we have here?
Here's the breakdown of different actions:
- First we list all the file with the FFF extension (*.FFF) in the current folder. You can of course change this to any which directory you like, or use a more sophisticated method to find/locate files, like the find command.
- Then, we use xargs with string replacement and pipe the names to the identify utility of the ImageMagick suite, which processes each filename and prints out attributes in the format of '%i %w %h\n', which means: filename, width, height, newline character so we separate output for each entry. Here, you have a freedom of expression - you can only search for width or height or other properties!
- Then, we grep wholeword (-w) entries that match a certain size, e.g.: width (640). You can egrep to catch multiple values, if you like, or even use regular expressions.
- Next, we only print the filenames of files that match the grep qualifier above. We actually print the first value with awk, as the output of the command is actually filename width height newline character, as in:
file1.jpg 640 480
file2.jpg 320 200
- Next, we filter out any empty lines - in my testing, sometimes, identify would print empty lines, so we don't want those in our results.
- We then pass the filenames to xargs once again, and copy them to a destination folder, which must exist. We use the -I option (you can also use the deprecated -i option) to make sure that filenames are parsed properly. If not, you may encounter the following error:
cp: target './file.jpg' is not a directory
Two-liner
The above should work great, but if you encounter an issue due to the delicate differences in how tools parse filenames, empty lines and newline characters, you can then simplify the one-line into a two-liner, where you first write the results into a text file, and then parse the text file for copy:
ls *.FFF | xargs -I{} identify -format '%i %w %h\n' {} | grep -w XXX | awk '{print $1}' | tee list.txt
cat list.txt | grep -v ^$ | xargs -I cp {} "destination folder"
For instance, we copy all the PNG images with either dimension set to 800 px:
ls *.png | xargs -I{} identify -format '%i %w %h\n' {} | grep -w 800 | awk '{print $1}' | tee list.txt
cat list.txt | grep -v ^$ | xargs -I cp {} ./dir-only-big-files
Conclusion
There. Now, I am certain you can propose a dozen different methods and tweaks that will accomplish the same, perhaps even more elegantly than what I wrote. If so, please email me with your suggestions, and I might add them to this tutorial. The purpose of this article is not to be the holy grail of scriptology, but a simple solution for a common need. And it does the job well.
Anyway, if you have tons of images, photos, screenshots, whatever, of varying sizes and attributes, you can use the Linux command-line to filter them out in a clever way, plus the ImageMagick identify command. We're even talking things like size, color mapping and more. Noice. Hopefully, you will find this rather useful. Take care.
Cheers.