One for the script kiddies

My scripting is woefully bad must do some more work on it, however in the meantime I need a script to do the following:

Recurse a directory tree from current directory. Change all file and directory names found to have leading capital letters on all words.

So:

foo/bar/foobar file name would change to Foo/Bar/Foobar File Name

Any help appreciated guys.

well you’ll want to start with something like:

find . > /tmp/filelist
cat /tmp/filelist | while read INFILE
do

done

quite what to do in the middle is the tricky bit - you can use “cut” to grab the first letter of the filename/dirname, but I’ve no idea if there’s a “to_caps” command you could use, maybe something in “sed” ?
else it’ll be a huge switch-case statement to check if the output of the “cut” is a then replace with A etc etc yawn :smiley:

something to start you off anyway.

Hmmm.

Any spaces or funny characters in the file names ?

If not the following is a start.
You’ll need to expand the sed line to cope with the rest of the alphabet
Substitute the mv for a cp and prefix $newname with an alternative path like /nfs/test$newname to copy it if you want to test without risking data.

find . | while read line
> do
> newname=echo $line |sed -e 's:/a:/A:g' -e 's:/b:/B:g' -e 's:/c:/C:g' -e 's:/d:/D:g'
> echo mv $line $newname
> done

-e ‘s:/a:/A:g’
Is a two character switch using : as a sed command delimiter, looking for /a swapping for /A and repeating for all other defined characters

Theres an easier way to do it with tr I think but I ran out of Arsed :slight_smile:

#!/usr/bin/perl

use File::Find;

# Fill this array with separator characters
@seps = (" ", "_");

finddepth(\&wanted, "tree");

exit(0);

sub wanted() {

  $filename = $oldfile = $_;

  for $sep (@seps) {
    $newfile = "";
    for $file1 (split($sep, $filename)) {
      if ($newfile eq "" ) { $newfile .= "\u$file1"; }
      else                 { $newfile .= "${sep}\u$file1"; }
    }
    $filename = $newfile;
  }

  print  "$File::Find::dir :: $oldfile --> $newfile
";
  rename "$oldfile", "$newfile";
}

tree is the name of my test folder and is not renamed by this script

I wish I knew more of this stuff. Nice going Kev :thumbsup:

Pah!

Mine works in five lines
:moon:

But you also need to capitalise the letters after a space. You may want to capitalise after an underscore or dash. That’s a lot of typing :eek:

You could reduce that to sed -e ‘s:[/ _][a-z]:\U&:g’ which will capitalise after a slash, space, or underscore. The problem is directories - this script will try to rename every directory in a long path in one go; looks good when echoed, but sadly doesn’t work :frowning: as find is still looking for the original path name.

The Perl script could do with some tweaks:
Pass the containing directory and separators as parameters …

[QUOTE=Kevin;410936]But you also need to capitalise the letters after a space. You may want to capitalise after an underscore or dash. That’s a lot of typing :eek:

You could reduce that to sed -e ‘s:[/ _][a-z]:\U&:g’ which will capitalise after a slash, space, or underscore. The problem is directories - this script will try to rename every directory in a long path in one go; looks good when echoed, but sadly doesn’t work :frowning: as find is still looking for the original path name.

The Perl script could do with some tweaks:
Pass the containing directory and separators as parameters …[/QUOTE]

…Must read the Specification document more closely…

generate a list of directories with find -type d| tac
Split prefix path and trailing name out on each line with basename and dirname.
Do the to upper conversion on the basename output
Deal with spaces, ampersands and any other frigging annoying character windows has put in the filenames.
Move directory to new name
Test return from move command ( I bet theres some duplicates ) and log errors

As the find output is reversed with tac it should work from the longest path first renaming bottom directories first and not fall over itself part way through.

Then rename the files with a similar bit of script but limit with find -type f

All in about 15 lines of bash

You still with us Mojo ?