EN
Bash - detect PNG, JPG, GIF file using file bytes (magic numbers in file)
10
points
In this short article, we would like to show how in Bash, detect PNG, JPG, or GIF files when we don't know file extension - that king of detection uses magic numbers located inside the file).
Quick solutions (use the following commands):
1. JPEG file test:
[ "$(xxd -s 6 -l 4 -p "/path/to/image.jpg")" = "4a464946" ] && echo "is JPEG" || echo "is not JPEG"
2. PNG file test:
[ "$(xxd -s 1 -l 3 -p "/path/to/image.png")" = "504e47" ] && echo "is PNG" || echo "is not PNG"
3. GIF file test:
[ "$(xxd -s 0 -l 3 -p "/path/to/image.gif")" = "474946" ] && echo "is GIF" || echo "is not GIF"
Practical example
Example detect_image_type.sh
file content:
#!/bin/bash
function is_jpg() # args: file_path
{
# J F I F (as chars)
# 4a464946 (in hex)
[ "$(xxd -s 6 -l 4 -p "$1")" = "4a464946" ] && return 0 || return 1
}
function is_png() # args: file_path
{
# P N G (as chars)
# 504e47 (in hex)
[ "$(xxd -s 1 -l 3 -p "$1")" = "504e47" ] && return 0 || return 1
}
function is_gif() # args: file_path
{
# G I F (as chars)
# 474946 (in hex)
[ "$(xxd -s 0 -l 3 -p "$1")" = "474946" ] && return 0 || return 1
}
# Usage example:
echo -e "\n--------------------------------\nJPG files:\n";
for file_name in *.*
do
is_jpg "$file_name" && echo "$file_name"
done
echo -e "\n--------------------------------\nPNG files:\n";
for file_name in *.*
do
is_png "$file_name" && echo "$file_name"
done
echo -e "\n--------------------------------\nGIF files:\n";
for file_name in *.*
do
is_gif "$file_name" && echo "$file_name"
done
echo -e "\n--------------------------------\n"
echo -e "DONE!\n"
Running:
./detect_image_type.sh
Example output:
--------------------------------
JPG files:
picture.jpg
mountains.jpeg
river.tmp
sun.tmp
--------------------------------
PNG files:
ball.png
square.unknown
--------------------------------
GIF files:
animation.dat
--------------------------------
DONE!