Linux Blog

Putting it all together

Filed under: Shell Script Sundays — TheLinuxBlog.com at 12:40 pm on Sunday, October 28, 2007

Since the start of this column I’ve shown many techniques that can be used in Shell Scripts. Today I will show an example of what can be done when it is all put together.

To start off, I recently made a photo tagging script for a friend of mine. The purpose of this script is to basically gather information about the pictures such as the month, year and who are in the photo. It also allows people to upload new pictures. The information is stored in a MySQL database and photos are kept in one folder as a unique hash of the file.

The script that I am going to show this week basically hashes the filenames and creates the SQL code that is needed to import the records into the database.

The full script source code can be found here.

The first thing the script does is use getopts to put the options into variables. For more information on how to do this can be found in my blog post on Creating Script Parameters With getopts.

### Get passed options.
while getopts ":s:d:f:" ARG; do
case "${ARG}" in
s) dirSource="${OPTARG}";;
d) dirName="${OPTARG}";;
f) sqlDump="${OPTARG}";;
esac
done

Once the options have been put into variables the following is ran:

The only thing that is needed for this script to run is a path. All that the above does is make sure that a path was specified. If not it calls the function usage and exits the script.
Here is the usage function:

usage () {
echo -e "\nUsage: $0 -s [ -d -f ]\n"
echo -e "\t-s: specifies the source directory. (required)"
echo -e "\t-d: specify the destination."
echo -e "\t-f: create an sql dump to import into MySQL.\n"
}

The main loop is very simular to my When Photoshop Fails article as it uses find. Except it finds all jpg files regardless of case. It does this by using [j,J][p,P][g,G] as the file mask.

find "${dirSource}" -name *.[j,J][p,P][g,G] | while read sourceFile; do

The following checks to make sure that dirName is not empty. The dirname command takes a file and will extract the directory name from it. So, if a directory to put the moved files in wasn’t given at run time, the directory that the new picture gets put in is the same as the old one.

### We don't want to overwrite this var by mistake.
if [ -z "${dirName}" ]; then
dirName=`dirname "${sourceFile}"`
fi

This is the last part of the loop. It uses md5sum to create a hash of the file is piped to awk which is used to print the actual hash. It then moves the file to the directory that was created from above. Create SQL and cleanVar are both functions that are called to do another task.

fileHash=`md5sum -b "${sourceFile}" | awk '{print $1}'`
mv "${sourceFile}" "${dirName}/${fileHash}.jpg"
createSQL; cleanVar

The createSQL function is used in this script to take the hash and insert it into the table that the PHP web app uses. At the moment the script just creates the SQL. The importing has to be done manually.

createSQL () {
if [ -n "${sqlDump}" ]; then
echo "INSERT INTO \`pictures\` (\`img_name\`) VALUES('${fileHash}');" >> "${sqlDump}"
fi
}

The cleaning function unsets fileHash which is the hash of the file that was just copied. It also does a check to see if the $dirName variable needs to be unset. It does this by checking to see if the dirName is the same as the directory name of the source file and unsets $dirName if it is.

### Clean up variables before next loop (precautionary).
cleanVar () {
unset fileHash
 
### We don't want to clean this var unless we have to.
if [ "${dirName}" == "$(dirname ${sourceFile})" ]; then
unset dirName
fi
}

Its a pretty simple script and uses a lot of what I’ve gone over in previous posts. Heres the script in action (the directory that the pictures are to be copied to must exist.)

owen@the-linux-blog:$ ls
JPG-hasmove.sh  NewPics  Pictures
owen@the-linux-blog:$ ls Pictures/
1.jpg  2.jpg  3.jpg  4.jpg  5.jpg
owen@the-linux-blog:$ ls NewPics/
owen@the-linux-blog:$ ./JPG-hasmove.sh -s Pictures/ -d NewPics -f SQLFile.sql
owen@the-linux-blog:$ ls
JPG-hasmove.sh  NewPics  Pictures  SQLFile.sql
owen@the-linux-blog:$ ls Pictures/
1.jpg  2.jpg  3.jpg  4.jpg  5.jpg
owen@the-linux-blog:$ ls NewPics/
294e8b2c5a9c4d61de67a166cd8e8e29.jpg  9b3270fc78fdf3920d0e44197da52944.jpg
6ef86ca6dcfb2467b46ed9d929fd4070.jpg  f353aa857522586d08ad7956090c8566.jpg
8aa35639bc0d3e7abc23c0b70acce08d.jpg
owen@the-linux-blog:$ cat SQLFile.sql
INSERT INTO `pictures` (`img_name`) VALUES('8aa35639bc0d3e7abc23c0b70acce08d');
INSERT INTO `pictures` (`img_name`) VALUES('f353aa857522586d08ad7956090c8566');
INSERT INTO `pictures` (`img_name`) VALUES('294e8b2c5a9c4d61de67a166cd8e8e29');
INSERT INTO `pictures` (`img_name`) VALUES('6ef86ca6dcfb2467b46ed9d929fd4070');
INSERT INTO `pictures` (`img_name`) VALUES('9b3270fc78fdf3920d0e44197da52944');

If you have a use for the script or this has helped you some please let me know, I always like to hear from people that find my posts useful. Until next time: Happy Shell Scripting!

Man Pages for commands in this post »

find
echo
mv
unset

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>