1.31.2016

Using Unix to Change Filenames

I have recently been trying to standardize my file names to keep a better consistency. I have decided to use all lowercase letters rather than the title case that I have been using.

View inside a folder that has file and folder names using title case (combination of upper- and lowercase letters.

I knew there must be a quick way of making these changes using Unix commands in Terminal. After a quick Google search, I found this site. After using the cd command to get in the directory, the syntax to change everything to lowercase looks like this:

for f in * ; do mv -v $f `echo $f | tr '[A-Z]' '[a-z]'`; done

To understand how this works, let's parse the syntax. First the semicolon is how we put multiple commands on a single line. It is akin to hitting <enter>. So it may be a bit easier to understand if we format this in a different manner.

for f in *
  do mv -v $f `echo $f | tr '[A-Z]' '[a-z]'`
done

The first and last lines are executing a FOR loop. The f in * just says do something (in this case the something is the commands issued in the second line) for each filename in the directory, that is where the * comes in. The f is an arbitrary variable name.

The do command of the second line tells Unix to actually do what follows it. The heart of this command is mv. In Unix-speak, mv can either be used to move files or rename files, depending on what comes after it. In this case, we use it to rename files. The -v is an optional flag that tells Unix to print to the screen everything that mv is doing (verbose mode). In general the structure of using mv to rename files looks like this:

mv old_filename new_filename

From the FOR loop, the name of each file is stored in the variable f. Thus we can get that name by accessing $f (the old filename). Notice the new filename is not given explicitly, but is a series of Unix commands. This is enclosed in a set of backticks (`commands`). Everything typed between backticks is evaluated (executed) by the shell. (The mathematical equivalent would be enclosing this in parentheses so order of operations is followed.)

The series of commands executed is

echo $f | tr '[A-Z]' '[a-z]'

This echos back the filename ($f) and then pipes it into the translate (tr) command. This is like a pipeline, where the output of a one process is fed as input into a subsequent process. This is that vertical bar (|). SO the output of echo (the filename) is fed into the tr command.

The tr command translates the first thing into the second thing. Since these are characters, they are both enclosed in quotation marks. Both the first and second component are calling regular expressions. The first component, [A-Z], looks for uppercase letters, which are then translated into lowercase letters, [a-z], the second component.

After executing the command, the verbose flag outputs the following:

Andy -> andy
Dad -> dad
Fractals-and-Chaos-Workshop-Pamphlet.pdf -> fractals-and-chaos-workshop-pamphlet.pdf
Grandpa -> grandpa
Soccer -> soccer


The result is all the filenames (or folder names) are now lowercase

The same directory after running the commands.

There are other ways to do this as well. For example, the regular expressions can be changed so the commands are:

echo $f | tr '[:upper:]' '[:lower:]'

Be careful if you use these commands. You can accidentally write over a file if it has the same name. For example if your directory contained two files,

myFile.doc
myfile.doc

and you issued this command, you would write over the 'myfile.doc' file.






No comments: