I'm trying to create shell script that returns the largest picture in total dimensions pixel size?

For example:

I have many directory over 7000+, each directory have images:

picture_1.png = 800x600
picture_2.png = 80x100
picture_3.png = 80x640
picture_4.png = 500x630

p_1.png = 800x600
p_2.jpeg = 800x1000
p_3.png = 180x1640
p_4.gif = 500x30

So the result expected is:

 the largest one in dir_1 is: picture_1.png 
 the largest one is dir_2 is: p_2.png 

So I was thinking is best way is to find out the total of dimensions after collect the figures .. therefor I try to create bash script with sips command that can collect the figures

Here example :

 for f in *;
 far=$( cd $f/OEBPS/image/ | ls * | egrep 'jpg|png|jpeg')

 W=$( sips -g pixelWidth $far | cut -f 2 -d":" )
 H=$( sips -g pixelHeight $far | cut -f 2 -d":" )

 coll=$(expr $W + $H)
 echo $f total is: $coll
 cd -

But got error on result.

Any idea or better way?

  • 1
    What error do you see? – glenn jackman Apr 25 '15 at 15:12
  • 1
    For the "largest" image, do you want to consider the perimeter or the area? – glenn jackman Apr 25 '15 at 15:18
  • Don't do "cd" in scripts. You can iterate from your current directory over the files too. And don't do "ls" in scripts. In bash, you can do: for f in $f/OEBPS/image/*{png,jpeg,jpg}. A ls will bite you if you have blanks and such in fillenames. – user unknown Apr 25 '15 at 17:18
  • Also, what if two or more images in the same directory have the same size ? – don_crissti Apr 25 '15 at 22:00
  • I've fix by add identify "$image" 2> /dev/null ... anyhow thanks for your effort ... last think .. i want to the result print with urlencode for example file: tadlil kalamy fmt.png to be tadlil%20kalamy%20fmt.png I'm use MAC OS X – jassim mishal Apr 25 '15 at 22:46

here's a way to get the height and width in one step:

IFS=x read w h < <(identify "$file" | grep -oP '\d+x\d+(?=\+)')

identify is part of the ImageMagick package.

Your "$far" is surely not what you want:

for dir in */OEBPS/image/; do
    for image in "$dir"/*.{jpg,png,jpeg}; do
        IFS=x read w h < <(identify "$image" | grep -oP '\d+x\d+(?=\+)')
        echo $((w*h)) "$image"
    done | sort -n | tail -1 | {
        read size file
        echo "largest in $dir is $file"

Actually, identify can take several files, so a more efficient technique:

for dir in */OEBPS/image/; do
    identify "$dir"/*.{jpg,png,jpeg} |
    awk '{split($(NF-6), a, /x/); split($0, b, /[[]/); print a[1]*a[2], b[1]}' |
    sort -n | tail -1 | {
        read size file
        echo "largest in $dir is $file"

The awk command is a bit complicated because I want to handle image names that may contain spaces

  • first script seems is good but need little fix .. i got the result but in same-time i got error like: /OEBPS/image/*.png': No such file or directory @ error/blob.c/OpenBlob/2675 /OEBPS/image/*.jpeg': No such file or directory @ error/blob.c/OpenBlob/2675 seems the script try to find all dir with jpg,jpeg,png and print it to me just need to hide that – jassim mishal Apr 25 '15 at 22:25
  • add shopt -s nullglob before the for loop – glenn jackman Apr 25 '15 at 23:09
  • you could also discard identity's stderr: identity "..." 2>/dev/null – glenn jackman Apr 25 '15 at 23:13
for f in /OEBPS/image/*{png,jpg,jpeg}
  id=$(identify "$f") 
  size=$(echo ${id} | sed -r 's/.* (JPEG|PNG) ([0-9]+)x([0-9]+) .*/\2*\3/')   
  if (( area >= max ))
echo $max $file
  • Don't use ls for iterating over files in scripts - blanks in filenames will brake them.
  • Don't cd around.
  • We don't need sorting to find the biggest file by area.
  • For doing arithmetic in bash, you don't need expr, but $((a*b)).

Identify needs ImageMagick.

The sed-command will fail if your filename looks too close like the output of identify.

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.