Søren Lund (slu) wrote,
Søren Lund

  • Location:
  • Mood:

Fixing the case of all files and directories

When moving files around between Linux/UNIX and Windows, you sometimes end up with files and directories with the wrong case. For example UPPERCASE names a suddenly lowercase or CamelCase becomes all UPPERCASE.

If you're (only) a Windows user, then you might think "the case of a filename isn't important - it's case insensitive." True, on Windows, but not true on Linux/UNIX. On a Linux system you can have three files called README, ReadMe and readme placed in the same directory, and they will coexists fine.

Most of the time such changes in case doesn't really break anything (they are just annoying). You might end up with the same file twice (remember "FILE.TXT" and "file.txt" can coexists).

But occasionally the case does matter. For example the name of Java source file should match the class name, including the case.

I just had a directory full of files and directories, that I'd moved from a Windows machine to a Linux machine. The original (and correct) case were all UPPERCASE, but that was lost, and all files and directories were now all lowercase.

To fix it I did the following from my bash-prompt:

$ for n in $(find directory| tac); do mv $n $(dirname $n)/$(tr [:lower:] [:upper:] <<< $(basename $n)); done

Let's see that again, as a "script":

for n in $(find directory | tac); do
  mv $n $(dirname $n)/$(tr [:lower:] [:upper:] <<< $(basename $n));

First line is a simple for-loop, but what is it looping over? The $(...) construct is called a command substitution. The commands inside the parenthesis are called and the output is fed back into the line. It's a bit line having a shell within a shell, you can even have command substitution within a command substitution, which I'm using on the next line. But back to the first line: the "find directory | tac" simply finds all files and directories withing the directory called "directory" (replace with you own directory name). The tac filter in the end reverses the list (note that tac is cat in reverse, funny eh?)

The inner part of the loop (the second line) renames (moves = mv) the file or directory we just found (and stored in $n) to a new name. The new name is constructed as "$(dirname $n)/$(tr [:lower:] [:upper:] <<< $(basename $n))". The dirname and basename command simple cuts off the directory and the filename parts of the complete path returned by find. But I want to make all name UPPERCASE, a simple call to tr does the magic (using the output from basename as input.)

That wasn't so hard, was it?
Tags: shell upper lower case
  • Post a new comment


    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded