0

I'm writing a bash script to find all the images in the folder and find if they have corrupt endings with ImageMagick.

This is the command I'm trying to automate:

identify -verbose *.jpg 2>&1 | grep "Corrupt" | egrep -o "([\`].*[\'])"

The issue I'm having is with storing the identify command into a variable.

There are multiple types of quotes that are present in the command I keep getting an error line 8: corrupt: command not found

#!/bin/bash
# This script will search for all images that are broken and put them into a text file

FILES="*.jpg"

for f in $FILES
do
  corrupt = "identify -verbose \"$f\" 2>&1 | grep \"Corrupt\" | egrep -o \"([\`].*[\'])\""

  if [ -z "$corrupt" ]
  then
    echo $corrupt
  else
    echo  "not corrupt"
  fi
done

Is there a way to escape that command correctly?

UPDATE:

Some progress:

#!/bin/bash
# This script will search for all images that are broken and put them into a text file

FILES="*.jpg"

for f in $FILES
do
  echo "Processing $f"
  corrupt="identify -verbose $f 2>&1 | grep \"Corrupt\" | egrep -o \"([\`].*[\'])\""

  if [ -z "$corrupt" ]
  then
    echo $corrupt
  else
    echo  "not corrupt"    
  fi

done

This no longer throws an error, but it looks like it just stores the variable as a string.

How can I run this command?

UPDATE: Some progress. Now the command is running:

#!/bin/bash
# This script will search for all images that are broken and put them into a text file

FILES="*.jpg"

for f in $FILES
do
  echo "Processing $f"

  corrupt=`identify -verbose $f | grep \"Corrupt\" | egrep -o \"([\`].*[\'])\"`

  $corrupt

  if [ -z "$corrupt" ]
  then
    echo $corrupt
  else
    echo  "not corrupt"    
  fi

done

But the output of pipes is separate:

Processing sdfsd.jpg
identify-im6.q16: Premature end of JPEG file `sdfsd.jpg' @ warning/jpeg.c/JPEGWarningHandler/387.
identify-im6.q16: Corrupt JPEG data: premature end of data segment `sdfsd.jpg' @ warning/jpeg.c/JPEGWarningHandler/387.

I just need the final `sdfsd.jpg' string.

5
  • @Quasímodo Did I misspell something? I tested the command separately and it's working correctly. I'm new to bash scripting so I might be misunderstanding. Oct 6, 2021 at 21:16
  • 1
    corrupt="identify..." sets the variable to the given literal value, just like FILES="*.jpg". I think you're looking for command substitution: mywiki.wooledge.org/CommandSubstitution
    – ilkkachu
    Oct 6, 2021 at 21:17
  • @ilkkachu Thanks! I already figured out the backticks will work better. Now the pipes are not running at the same time for some reason. Is there a way to run them all at the same time as the original command so I could get the final string? Oct 6, 2021 at 21:35
  • 3
    If you're learning then quickly unlearn backticks and instead use $( ... ) for command substitution Oct 6, 2021 at 22:29
  • @roaima already did. Unfortunately still cannot capture the final output of the file name. Oct 6, 2021 at 22:34

1 Answer 1

3

What you are probably looking for is a way of identifying corrupt images. It's easy to query the identify tool for its exit-status to see whether it managed to identify the image file or not.

#!/bin/sh

for name in *.jpg; do
    if identify -regard-warnings -- "$name" >/dev/null 2>&1; then
        printf 'Ok: %s\n' "$name"
    else
        printf 'Corrupt: %s\n' "$name"
    fi
done

The above uses the exit-status of identify to determine whether the file was corrupt or not. The -regard-warnings option escalates the warnings you mention into errors turn, which makes them affect the exit-status of the utility.

You very seldom need to store actual globbing patterns in variables. You can often get a utility's success/failure status by testing its exit-status like what we show above without parsing the tool's output.

For older ImageMagick releases (I'm using 6.9.12.19), use convert instead of identify.

#!/bin/sh

for name in *.jpg; do
    if convert -regard-warnings -- "$name" - >/dev/null 2>&1; then
        printf 'Ok: %s\n' "$name"
    else
        printf 'Corrupt: %s\n' "$name"
    fi
done

The above loop tries to convert each image, and if it fails to process an image file, it is detected by the if statement. We discard the result of the conversion operation.

19
  • Thanks, but this is failing on my test files. Here is a test file: ufile.io/sz8gn4e8 Oct 6, 2021 at 22:22
  • 1
    @KalvinKlien See added bit.
    – Kusalananda
    Oct 6, 2021 at 22:55
  • 1
    @KalvinKlien It is converting the image, but the converted image is thrown away (- means write the result to standard output, and we redirect this to /dev/null). The original image files are not modified.
    – Kusalananda
    Oct 6, 2021 at 22:58
  • 1
    @KalvinKlien You will notice that neither of these files are detected as corrupt by identify -verbose either. I wonder whether they were saved in their truncated state. Both contains a creator comment CREATOR: gd-jpeg v1.0.
    – Kusalananda
    Oct 7, 2021 at 5:48
  • 1
    @they I figured it out, I needed to pull samples from server itself because Cloudflare was modifying the files, it was "fixing" them. Thanks for all the help. The script works correctly! Oct 7, 2021 at 19:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .