1

I am trying to find all photos that are not equal to a 256 pixels in height and length and move them to a new folder. So far I was able to write up the following code in the terminal that outputs in to the terminal a list of all the photos that math the criteria:

find . -iname "*.jpg" -type f | xargs -I{} identify -format '%w %h %i' {} | awk '$1!=256 || $2!=256'

Now I wish to move all of these photos to a new folder. I tried the following:

find . -iname "*.jpg" -type f | xargs -I{} identify -format '%w %h %i' {} | awk '$1<300 || $2<300' -exec mv "{}" ~/path_to_location/ \;

I am getting an error that there is

no such file or directory named exec

and also:

xargs identidy: terminated by signal 13

Would love your help Thanks

Raffa
  • 32,237
  • 1
    This would be no surprise. The find command ends after the first pipe symbol |. Your -exec is seen as an argument to your awk command, and of course, awk does not know what to do with that. – vanadium Aug 17 '22 at 10:49

2 Answers2

0

In bash, you can do it in a for loop like so:

for f in *.jpg
do 
     if [ -f "$f" ] # Check if it is a file
     then
        w=$(identify -format '%w' "$f") # Get width
        h=$(identify -format '%h' "$f") # Get hight
        [[ "$w" -lt 300 || "$h" -lt 300 ]] && # Check if width or hight are less than 300
        echo mv -- "$f" ~/path_to_location/ # Move the file ... "echo" is for simulation only ... remove "echo" when satisfied with the output to move files.
    fi
done

Related references:

Raffa
  • 32,237
0

I think what you're aiming for is something like

find . -iname "*.jpg" -type f -exec identify -format '%w %h %i\n' {} + | 
    awk '($1 != 256 || $2 != 256) {print $3}' | xargs -I{} echo mv -n -- {} path/to/newdir/

(echo added for dry-running the command first). However, there's an obvious problem that awk's {print $3} will break if the filename %i contains whitespace. If there's another character that you can guarantee not to be present in %i, you could change the format to use that, for example -format '%w:%h:%i\n' and then modify the awk field separator accordingly i.e.

find . -iname "*.jpg" -type f -exec identify -format '%w:%h:%i\n' {} + | 
  awk -F':' '($1 != 256 || $2 != 256) {print $3}' | xargs -I{} echo mv -n -- {} path/to/newdir/

For filenames containing whitespace but not newlines you could use the following bash shell construct

find . -iname "*.jpg" -type f -exec identify -format '%w %h %i\n' {} + | 
  while read -r w h i; do 
    ((w != 256 || h != 256)) && echo mv -n -- "$i" path/to/newdir/ 
  done

which gets around the problem of word-splitting because bash's read slurps everything after the first two IFS-separated fields into variable i.

To make it handle any whitespace, including newlines, you'd need to set the delimiter to the null character \0 in place of \n - unfortunately ImageMagick does not appear to support that. See ImageMagick: Percent Escape Handling.

steeldriver
  • 136,215
  • 21
  • 243
  • 336