Reputation: 345
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
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
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
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
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