user2735454
user2735454

Reputation: 345

BASH - Renaming pictures based on file type

I'm a bit frustrated here with trying to get what seems like a simple bash script to run properly. I believe this is due to very long file names, or spaces within the file.

In short, I'm trying to pull data from the file command, and rename pictures in a directory to their proper file type as some seem to be mis labeled. For example a .png file is actually a .jpg file. Which results in some image viewers not displaying them. Here is the script i'm using.

#!/bin/bash
for NAME in $(ls); do

if [ "$(file $NAME|grep GIF)" ]; then

echo "Renaming ${NAME} to ${NAME%.*}.gif"
mv ${NAME} ${NAME%.*}.gif

elif [ "$(file $NAME|grep JPG)" ]; then

echo "Renaming ${NAME} to ${NAME%.*}.jpg"
mv ${NAME} ${NAME%.*}.jpg

elif [ "$(file $NAME|grep PNG)" ]; then

echo "Renaming ${NAME} to ${NAME%.*}.png"
mv ${NAME} ${NAME%.*}.png

else

echo "No Change For ${NAME}"

fi
done

The echo at the end was just to see why it was failing, this is what I see:

No Change For 20097489744.jpeg
No Change For 24902583463

Then it just hangs, why? Because I believe that file contains spaces... I looked around a bit on mass renaming all the files in the directory by just incrementing the file names up, IE: 1.jpg 2.png 3.gif however EVERYTHING I have found online was not to increment a file rename job, but rather to remove numbers from the name and things like it.. So, I've hit a wall, short of renaming 130K files by hand (Not going to happen! lol)

I''d highly appreciate any input from the brainiacs out there!

Thanks and happy holidays!

Upvotes: 0

Views: 1071

Answers (4)

fitorec
fitorec

Reputation: 1042

If you have ImageMagick installed, you can try with identify command.

For example if the 24902583463.png file is in really a .jpg file you can execute:

#command
identify 24902583463.png
# out
24902583463 JPEG 800x600 800x600+0+0 8-bit DirectClass 304KB 0.000u 0:00.000

#Now get the typeFile:
identify -format "%m" 24902583463.png
# Output
JPE

# Get only name (without extention)
identify -format "%t" 24902583463.png
24902583463

# Get corrent extension (without name)
identify -format "%e" 24902583463.png
png

All in one script:

ls | while read NAME ; do
    identify -quiet "$NAME";
    if [ "$?" -eq "0" ]
    then
        FILE_NAME=$(identify -format "%t" "$NAME");
        FILE_EXT=$(identify -format "%e" "$NAME");
        FILE_TYPE=$(identify -format "%m" "$NAME" | tr '[:upper:]' '[:lower:]');
        if [ $FILE_EXT != $FILE_TYPE ];
            then
            mv  "$NAME" "${FILE_NAME}.${FILE_TYPE}";
        fi
    fi
done

Upvotes: 0

tripleee
tripleee

Reputation: 189577

You need proper quoting throughout. Where you have ${NAME}, change it to "${NAME}" (or equivalently just "$NAME"). Where you have a bare $NAME, change that to "$NAME", too. Etc.

Also, for NAME in $(ls) is wrong; you most probably mean for NAME in * instead.

Finally, you might want to replace if [ "$(file $NAME|grep GIF)" ]; then ... with the simpler and more idiomatic if file "$NAME" | grep -q GIF; then... (This was originally suggested in a -- now deleted -- answer by @phs.)

Upvotes: 1

Donovan
Donovan

Reputation: 15917

Here's a complete shell script solution which handles file names containing spaces and uses case:

#!/bin/bash
ls | while read NAME ; do

  FILE_NAME="${NAME%.*}"
  FILE_EXT="${NAME##*.}"

  case $(file "$NAME") in
    *GIF*  ) NEW_EXT='gif' ;;
    *JPEG* ) NEW_EXT='jpg' ;;
    *PNG*  ) NEW_EXT='png' ;;
    *      ) NEW_EXT='' ;;
  esac

  if [[ -n "${NEW_EXT}" && "${FILE_EXT}" != "${NEW_EXT}" ]] ; then
    echo "Renaming ${NAME} to ${FILE_NAME}.${NEW_EXT}"
    mv "${NAME}" "${FILE_NAME}.${NEW_EXT}"
  else
    echo "No Change For ${NAME}"
  fi
done

I've intentionally kept it simple, but let me know if you have any questions

Upvotes: 2

cdarke
cdarke

Reputation: 44364

If your filenames contain spaces then use :

mv "$NAME" "${NAME%.*}.png"

By the way,

 [ "$(file $NAME|grep GIF)" ]; 

can save a child process by using:

 [[ $(file $NAME) == *GIF ]]; 

When using grep, you probably should use grep 'GIF$', otherwise it would find GIF anywhere in the filename.

Upvotes: 1

Related Questions