Posted in How To

Extracting and Organizing with Bash

Extracting and Organizing with Bash Posted on October 22, 20243 Comments
Jed Reynolds has been known to void warranties and super glue his fingers together. When he is not doing photography or fixing his bike, he can be found being a grey beard programmer analyst for Candela Technologies. Start stalking him at https://about.me/jed_reynolds.
(Last Updated On: November 10, 2024)

Long week? Yeah, me too. I have my heavy metal Linux band in the motel room and no customers to attend to at the moment…let’s do some Bash scripting! Remember the “thumbnailing” script I did a few weeks ago? This is the script I use before doing thumbnails. It’s actually a bit more trippy and uses another script which I’ll cover in the next installment.

I begin by getting a temporary file setup:

#!/bin/bash
set -e
DateFile="/tmp/image-dates.$$"
[ -z "$DateFile" ] && echo "no datefile, bye." && exit 1
[ -f "$DateFile" ] && rm -f $DateFile
touch "$DateFile"

We have a guard: did we screw up our file name? That’s almost irrationally cautious, so you might feel justified in deleting that guard. The $$ symbol is a quick way to get your process ID (PID). You can use this for many things, but it is reasonably unique with low-frequency usage (that is, a few times a day).

65535Process

You can only have 65535 process IDs, and there are 86400 seconds a day, so if you approach one process a second, you’ll get repeats. If we find an identical date file, let’s delete it anyhow and create a new one. (POP QUIZ: tell me a one-liner that does this.)

Turn that metal up! We’re about to “headbang” through a crazy lead solo of string manipulation:

ls *.jpg *.dng *.bmp *.tiff *.jpeg \
*.JPG *.DNG *.BMP *.TIFF *.JPEG 2>/dev/null \
| while read F
do
G=$( echo -n "$F" | perl -pe 'y/[A-Z]/[a-z]/' )
cmd="mv -v $F $G"
$cmd
done

Yeah! Let’s crush some upper-case file names! Why the 2>/dev/null though? Have you ever done an “ls * .txt” command just to get everything in your directory listed and followed by a warning: .txt: file not found ? Yeah. That error message, or those TIFF or JPEG files you probably won’t have will all give you that message. It’s a safe message to discard into /dev/null.

devnull

We’re taking each file name F, and piping it into perl and feeding it into the Sarlacc jaws of the y/// translator. This y/// operator is the perl equivalent to the ‘tr’ command: it translates one character pattern to another character pattern. We’re forcing all upper-case alphabetic characters into lower case characters. Why? Type in caps much? (The bassist does, the bastard.) Extra credit: give me the shell command that replaces that perl command.

Now G is the transformed name, and we just move the file from the original F value to the new G value. (POP QUIZ: Why, oh why would I assemble a string of this command? Could this be evidence of an erased echo statement?) Extra Credit: make this command safer for filenames with spaces in them.

Drum solo! We’re going to rattle out some dates with another wee utility called ImgDate.sh:

ls *.{jpg,dng,bmp,tiff,jpeg,gif,png} 2>/dev/null \
| while read F
do
echo -n "$F " >> $DateFile
~/bin/ImgDate.sh $F >> $DateFile
done

imagelist

Remember that the >> operator appends to files and echo -n prints stuff without a newline. Pay attention to spaces. We’re immediately going to use this output in a loop:

cat $DateFile | sort | uniq \
| while read D
do
echo "D $D"
imgfile=`echo "$D" | awk '{print $1}'`
imgdir=`echo "$D" | awk '{print $NF}'`
if [ ! -d "$imgdir" ]
then
mkdir -v $imgdir
fi
mv -v $imgfile $imgdir
done

What, another external program…awk? Isn’t that the sound your drummer makes after the fifth shot of Jagermeister? Hell yeah. Awk loves to toss out column values, so $1 is anything in the first column. What did we put in the first column of DateFile? Oh yeah…the drummer, no, the image file name. The last column is always $NF. Pop Quiz: Why not $2 in the second column? Warning: Don’t ask where why the drummer is called NF, he’s shy. Extra Credit #2: what if the file name has spaces in it?

tree

Now we need to clean the floor of our motel room: /tmp. Let’s wipe up $DateFile.

rm -f $DateFile

I’m going to drag the drummer off to the tour bus, but I’m going to leave you with one more puzzler: If I delete $DateFile at the end of this party, why do I bother deleting it at the start of the party as well? Think about it…

More great Linux goodness!

Jed Reynolds
Jed Reynolds
Jed Reynolds has been known to void warranties and super glue his fingers together. When he is not doing photography or fixing his bike, he can be found being a grey beard programmer analyst for Candela Technologies. Start stalking him at https://about.me/jed_reynolds.

3
Leave a Reply

Please Login to comment
3 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
3 Comment authors
John AlvordemarskJed Reynolds Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Jed Reynolds
Guest
Jed Reynolds

Today I learned how to lowercase/uppercase values in bash with ${,,} and ${^^}

emarsk
Guest
emarsk

All those * should better be ./*
See why at http://www.dwheeler.com/essays/filenames-in-shell.html , it’s an interesting read (as anything else from David Wheeler: his whole site is awesome).

John Alvord
Guest
John Alvord

Do any Linux/UNIX systems complain if the same name is used in source and target of mv? Thinking of already lowercased names.