to rename all my camera photos I need some string functions,
to put the creation date on all the jpg files I need … jhead.
Linux does not keep the creation date; it keeps the modified date. The date on the file changes as soon as you copy or edit it, like with a photo editor.
if you have not modified the image so that the creation and modified dates are still the same, you can put the modified date on the front of the file name this way:
given image names like DSC00123.jpg
for fi in *.jpg do num=${fi:4:5} fdate=stat -c %y $fi | cut -d ' ' -f1 fdt=${fdate:0:4}${fdate:5:2}${fdate:8:2} # (remove hyphens) rename DSC0 XX-$fdt- DSC0${num}* done
“Bash, an acronym for “Bourne-Again shell” is a pun on Stephen Bourne’s now classic Bourne shell. Bash has become a de facto standard for shell scripting on most flavors of UNIX.”
#, ##, and %, %%
$ MYVAR=foodforthought.jpg
$ echo ${MYVAR#*fo}
odforthought.jpg
$ echo ${MYVAR##*fo}
rthought.jpg
${MYVAR#*fo}
bash took MYVAR, found the first instance of “fo”, and returned what was after it.
${MYVAR##*fo}
found the last instance of “fo”, and returned what was after it.
$ MYFOO=”chickensoup.tar.gz”
$ echo ${MYFOO%.*}
chickensoup.tar
$ echo ${MYFOO%%.*}
chickensoup
${MYFOO%.*}
in reverse, found the first period, and returned what preceded it.
(found the lastperiod, and returned what was before it)
${MYFOO%%.*}
in reverse, found the last period, and returned what preceded it.
(found the first period, and returned what was before it)
$ foo=/tmp/my.dir/filename.tar.gz
We can use these expressions:
path = ${foo%/*}
To get: /tmp/my.dir (like dirname)
file = ${foo##*/}
To get: filename.tar.gz (like basename)
base = ${file%%.*}
To get: filename
ext = ${file#*.}
To get: tar.gz
“It’s important to understand that these use shell “globbing” rather than “regular expressions” to match these patterns.”
“we can do quite a bit of string parsing and manipulation directly within bash — which will allow our shell scripts to run faster with less overhead.”
Substring by numerical position
$ MYFOO=”0123456789abc”
$ echo ${MYFOO:7}
789abc
$ echo ${MYFOO:7:4}
789a
$ echo ${MYFOO:0:4}
0123
${MYFOO:7}
all the characters after the 7th
${MYFOO:7:4}
the first 4 characters after the 7th
${MYFOO:0:4}
the first 4 characters
String Length
${#string}
expr length $string
expr “$string” : ‘.*’
$ stringZ=abcABC123ABCabc # length=15
$ echo ${#stringZ}
15
$ echo `expr length $stringZ`
15
$ echo `expr “$stringZ” : ‘.*’`
15
String Position
echo `expr index “$stringZ” C12`
6
Numerical position in $string of first character in $substring that matches.
Truncate
#!/bin/bash
# quickly convert html filenames to htm
# only handles file extensions, not file names
for i in *.html; do
if [ -f ${i%l} ]; then
echo “${i%l} already exists”
else
mv $i ${i%l}
fi
done
now, how to use the functions to
How to put the creation date on your jpg’s and videos
1. install jhead: yum install jhead … or … use the gnome tool, system -> administration -> add/remove software
2. create a text file containing something like
#!/bin/bash for fi in *.jpg do jhead -nXX-%Y-%m-%d-%f $fi # XX- being any prefix you want on the file name #jhead -nXX-%Y%m%d-%f $fi # or, switch to this one without the dashes done
If your jpg’s are named
00123.jpg
00124.jpg
00125.jpg
etc.
after the script above, they will be something like
XX-2011-07-06-00123.jpg
XX-2011-07-07-00124.jpg
XX-2011-07-08-00125.jpg
if they were taken on July 6th, 7th, and 8th, for instance.
If your jpg’s are named
DSC00123.jpg
DSC00124.jpg
DSC00125.jpg
they will now be
XX-2011-07-06-DSC00123.jpg
XX-2011-07-07-DSC00124.jpg
XX-2011-07-08-DSC00125.jpg
and, you could remove the “DSC” with the rename command:
rename ‘-DSC0’ ‘-‘ *-DSC0*
to result in this:
XX-2011-07-06-00123.jpg
XX-2011-07-07-00124.jpg
XX-2011-07-08-00125.jpg
my camera also takes videos (and keeps them in another folder)
Each video is in 2 files:
1. a thumbnail .jpg, for some reason, named .THM and
2. a .mp4, the video.
Both are prefixed with MAQ or MAH, instead of DSC. I changed them all to DSC to make the rest of the script easier. I am going to remove the 3 letters anyway, regardless. I also lower cased the .jpg’s that were not already, to make that consistent also.
to rename them, I wrote this:
rename .THM .jpg *.THM
rename MAQ DSC MAQ*
rename MAH DSC MAH*
rename .JPG .jpg *.JPG
rename .MP4 .mp4 *.MP4
# some cameras, like windows make the images executable. THEY ARE NOT! And it is a security risk to accept images that are. I fix that.
chmod 644 *.jpg
chmod 644 *.mp4
Here is the hard part, the thumbnail .jpg has the creation date on it but not the .mp4. I need to get the date from the jpg and put it on the mp4.
for fi in DSC0*.jpg do jhead -nGr-%Y%m%d-%f $fi rename '-DSC0' '-' *-DSC0* done #rename '-DSC0' '-' *-DSC0* for MP in DSC0????.mp4 do num=${MP:4:5} #echo $MP $num for jpg in *${num}jpg do #echo $jpg ${jpg%%jpg} mv $MP ${jpg%%jpg}mp4 done done
A listing of commands within parentheses starts a subshell.
Variables inside parentheses, within the subshell, are not visible to the rest of the script. The parent process, the script, cannot read variables created in the child process, the subshell.
a=123
( a=321; )
echo “a = $a” # a = 123
# “a” within parentheses acts like a local variable.
Modulo (remainder of a division)
let “z = 5 % 3”
echo $z
2
# Assignment
a=879
echo “The value of \”a\” is $a.”
# Assignment using ‘let’
let a=16+5
echo “The value of \”a\” is now $a.”
#!/bin/bash
# int-or-string.sh
a=2334 # Integer.
let “a += 1”
echo “a = $a ” # a = 2335
echo # Integer, still.
uninitialized variables
echo “$uninitialized” # (blank line)
let “uninitialized += 5” # Add 5 to it.
echo “$uninitialized” # 5
# Conclusion:
# An uninitialized variable has no value,
#+ however it evaluates as 0 in an arithmetic operation.
command substitution
a=`echo Hello!` # Assigns result of ‘echo’ command to ‘a’ …