terminal batch rename (Linux)
Wed 15 July 2015 bash batch Linux , 0 comments
Mon 27 July 2015

My laptop is running Ubuntu 15.04 and lately I had to do some batch file renaming. No sweat, I searched online for a bit and found what I was looking for: the rename program written in Perl. Pretty cool (I said to my self), now I can do a bunch of renames super easily. But little did I know that on the machine (doesn’t run Ubuntu) I’m working at the office most of the time… there is no rename Perl program, there is a rudimentary rename program, but not satisfactory enough (and ancient as well for this era: written in 2000 as per it’s man page). Now the problems start…

Searching online, I found this nifty trick you can use with another (super Linux) program: sed. You can easily rename programs with the following (piped) commands:

ls {f_pattern} | sed 'p;s/{s_patternN}/{r_patternN}' | xargs -n2 mv
# ls {f_pattern}                   : list the files we want to rename based
#                                    on {file_pattern}
# sed 'p;s/{s_patternN/r_patternN}': 'p' instructs `sed` to print the file name
#                                    first, then 's/{s_patternN/r_patternN}'
#                                    substitutes {s_patternN} with {r_patternN}
#                                    and prints the result
# xargs -n2 mv                     : gets the output from `sed` and feeds it to
#                                    `mv` two lines at a time (because `-n2`)
#                                    as arguments

NOTE: wondering why there’s an 'N' in the search and replace patterns given to sed are you?! Good observation! That’s because we can give multiple search and replace patterns to sed as in sed 'p;s/EI//;s/_500/_00/;s/TEST/test/' (but these could be any other number of instructions delimited by ';', not just search-and-replace commands - look at the documentation for more advanced stuff: what does 'y/[A-Z]/[a-z]' do for example?!). The important bit to remember here is that we need the 'p' instruction to be the first (this prints the file name before altering it).

Pretty interesting, but there’s a catch. This doesn’t always work properly. Specifically it doesn’t work when the file names contain white spaces because xargs delimits the arguments (to be passed to mv) based on any white space. So you can see where this can go wrong…

There is good news though and not all is lost! xargs accepts the -0 argument which instructs it to create arguments using the NULL character as the delimiter instead of the '\n' (newline) character. This is good new because we only need one more thing in our pipe for this to work properly!

ls {f_pattern} | sed 'p;s/{s_patternN}/{r_patternN}' | tr '\n' '\0' | xargs -n2 -0 mv

See what we did here?! We were clever in using tr as an intermediary step between the output of sed and the input to xargs. tr is a program that translates (or better yet, replace characters) and in this case we instruct it to translate for us the newline '\n' character to the NULL character, i.e. '\0'.

Congratulations… you are now the proud owner of the best Linux terminal batch file rename trick that there is out there! Go on now and happy batch rename!