UNIX help: grep, sed, tr, regular expression question

I’m trying to write a shell script to go through and automatically rename all my mp3’s to a standard naming scheme, one of the key points being that I want the first letter of each word capitalized. This is where I’m running into my first major crash.

I tried doing


for i in *.mp3; do echo $i|sed 's/^[a-z]/[A-Z]/';done

as a test to see if I could capitalize the first letter of the name of each file, but then as you all know, I ended up with “[A-Z]ameo - word up.mp3” as a sample filename. So I tried doing all sorts of things, none of which worked. sed y/// and tr, on the other hand, happily uppercase all the letters, but that’s just as annoying as all lowercase.

So I’m still experimenting, but any advice would be hugely appreciated.


ls *.mp3 | grep -v "^[A-Z]" > oldnames
while read i
do
  echo $i | cut -c1 >> char1
  echo $i | cut -c2- >> char_remain
  cat char1 | tr '[a-z]' '[A-Z]' > char1.x
  paste char1.x char_remain | sed 's/   //' > newnames
done < oldnames
paste -d\; oldnames newnames > combnames
  #for some reason the plain-old tab delimiter
  #doesn't work for the following cut statemts
while read names
do
  oldna=`echo $names | cut -f1 -d\;`
  newna=`echo $names | cut -f2 -d\;`
mv $oldna $newna
done < combnames
rm combnames oldnames newnames char1 char_remain char1.x

It’s pretty tortured (I’m not a professional Unix programmer by any stretch), but it works.

What the ??? Where did all the extra line spaces come from? :confused:
They weren’t there in preview, I swear! :o

… but off the top of my head, the regex you need is:

/^[a-z]{1}/[A-Z]/

With awk:


ls -1 *.mp3 | gawk '{ print toupper(substr($1,1,1)) substr($1,2) }'

Or perl:


ls -1 *.mp3 | perl -n -e 'print ucfirst'

I thought you had your naming script working like months ago.

Yeah but that one only worked under very specific conditions: all it did was change artist - song.mp3 to artist – song.mp3

And if you remember, that one took me like an entire day to get working. hahaha

Here is my ksh solution:


#! /usr/bin/ksh
typeset -u upshift
for filename in *.mp3 ; do
    rest=${filename#?}
    char1=${filename%$rest}
    upshift=$char1
    echo mv $filename ${upshift}${rest}
done
exit 0

On preview, I am getting double spacing. I think the code feature is broken.

Well, I finally got it, and I did it all using sed, including a piece I grabbed from the USENET archive on google.
In case there’s anybody who’s as weak at shell scripting as I am, I’m posting my script here, fully commented. The part that does the actual work only takes up about 350 bytes, but I thought maybe somebody could learn from my trouble, so I spent 10 minutes explaining what I did (for all you guys who kick my ass at scripting, you aren’t the ones I wrote the comments for! ;))

Thanks much to all who posted help. Any further comment or criticism is welcome.

Detailed comments are the key to altering the script to meet changing needs. Great script. Undoubtedly you will end up wanting to change it in few months. Without those comments, you would end up started from scratch. Great job.