Rename unix utility - windows port

From Svendsen Tech PowerShell Wiki
Jump to: navigation, search

I wrote a Windows port of the Unix utility rename.pl - a Perl script initially authored by none other than Larry Wall. Apparently there are a few versions around, and I based this port loosely on the version I found on my Ubuntu 10.04 system, which presumably is the Debian rename.pl version.

There is no warning when the destination file already exists and the file will be overwritten! Test with a dry run first.

All the parameters can be used in the shortest uniquely identifying form. In the case of this utility, you can use single-letter parameters for all the parameters, such as "-d" instead of "--dryrun" or "--dry". The same applies to all the parameters.



Help Text And Parameters

PS C:\PowerShell> .\rename.exe

rename.exe : Rename a set of files according to a Perl substitution
             or transliteration expression. Created by Svendsen Tech.
             Author: Joakim Svendsen

Usage: rename.exe --subst "perl subst/tr expression" -glob "glob"
[--help] [--dryrun] [--nonverbose]

--help:  Print this help text.
--subst: Perl substitution expression or transliteration, as seen on the right
         hand side of the binding operator "=~" - usually s///. Each filename
         in "glob" will be renamed according to this.
--glob:  File glob as expanded by perl's glob() function. perldoc -f glob.
         For instance "*.mp3" to target all mp3 files.
--dryrun: Do a "dry run", meaning files won't be renamed, but you will see
          exactly what the script would do as output to the console. You
          will get output even if you specify --nonverbose.
--nonverbose: Non-verbose (no output). Not in effect on dry runs.


See perldoc perlre for a list of available flags and more information about
Perl regular expressions. See perldoc perlop for a description of s/// and
tr///. perldoc perlretut may also be of interest.

If an argument contains no spaces or shell meta characters, the quotes can
be omitted. If you are calling this from PowerShell, use a single-quoted
string and q() and qq() for strings inside the single-quoted string.

See http://www.powershelladmin.com/wiki/Rename_unix_utility_-_windows_port
for more information.

Examples:
rename.exe -s s/\.txt$/.log/ -g *.txt   - renames txt files to log files.
rename.exe -s tr/A-Z/a-z/ -g *.mp3  - makes "A-Z" in mp3 files all lowercase.


Examples

Some examples.

If you are going to use this utility from PowerShell, I strongly recommend you familiarize yourself with what I wrote about using Perl from PowerShell in this article as it also applies to the parameters you pass to this rename utility. The short version is that you should use a single-quoted string for the --subst and --glob parameters, and use q() and qq() for strings inside the single-quoted string parameter - such as when using the evaluate flag in a substitution regexp.

Example 1

So, in a directory, you have a bunch of files that have upper-case file names, and you want to lower-case them.

PS E:\temp\dirs> dir *.txt


    Directory: E:\temp\dirs


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        27.12.2011     18:28          8 C.txt
-a---        16.12.2011     10:23       2067 FIL.txt
-a---        27.12.2011     18:28          8 FILE1.txt

First you test with the --dryrun parameter to see what would happen with a simple transliteration:

PS E:\temp\dirs> perl .\rename.pl --subst 'tr/A-Z/a-z/' --glob '*.txt' --dryrun
Would rename 'C.txt'                     - to 'c.txt'
Would rename 'FIL.txt'                   - to 'fil.txt'
Would rename 'FILE1.txt'                 - to 'file1.txt'

This looks right, so we go ahead and remove "--dryrun":

PS E:\temp\dirs> perl .\rename.pl --subst 'tr/A-Z/a-z/' --glob '*.txt'
Renamed 'C.txt'                          - to 'c.txt'
Renamed 'FIL.txt'                        - to 'fil.txt'
Renamed 'FILE1.txt'                      - to 'file1.txt'
PS E:\temp\dirs> dir *.txt


    Directory: E:\temp\dirs


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        27.12.2011     18:28          8 c.txt
-a---        16.12.2011     10:23       2067 fil.txt
-a---        27.12.2011     18:28          8 file1.txt


PS E:\temp\dirs>

Example 2

But what if you want to upper-case them again? You might try the reverse transliteration, but that would also uppercase the extension, and for some reason you don't want this:

PS E:\temp\dirs> perl .\rename.pl --subst 'tr/a-z/A-Z/' --glob '*.txt' --dryrun
Would rename 'c.txt'                     - to 'C.TXT'
Would rename 'fil.txt'                   - to 'FIL.TXT'
Would rename 'file1.txt'                 - to 'FILE1.TXT'

So you can break out a regular expression with the /e flag, for code evaluation in the substitution part of the regexp. Here I use the Perl uc() function for upper-casing:

PS E:\temp\dirs> perl .\rename.pl --subst 's/(.+)\.txt$/uc($1) . q(.txt)/ei' --glob '*.txt'
Renamed 'c.txt'                          - to 'C.txt'
Renamed 'fil.txt'                        - to 'FIL.txt'
Renamed 'file1.txt'                      - to 'FILE1.txt'

Actually, I forgot to add the --dryrun parameter here to verify first, so be careful!

Example 3

Fortunately it's easily reversible in this case, simply by using lc() instead of uc():

PS E:\temp\dirs> perl .\rename.pl --subst 's/(.+)\.txt$/lc($1) . q(.txt)/ei' --glob '*.txt'
Renamed 'C.txt'                          - to 'c.txt'
Renamed 'FIL.txt'                        - to 'fil.txt'
Renamed 'FILE1.txt'                      - to 'file1.txt'

Example 4

Strip or add an extension from files:

PS E:\temp\dirs> perl .\rename.pl --subst 's/$/.old/i' --glob '*.txt'
Renamed 'c.txt'                          - to 'c.txt.old'
Renamed 'fil.txt'                        - to 'fil.txt.old'
Renamed 'file1.txt'                      - to 'file1.txt.old'

PS E:\temp\dirs> perl .\rename.pl --subst 's/\.old$//i' --glob '*.txt'
No files matched by glob

PS E:\temp\dirs> perl .\rename.pl --subst 's/\.old$//i' --glob '*.old'
Renamed 'c.txt.old'                      - to 'c.txt'
Renamed 'fil.txt.old'                    - to 'fil.txt'
Renamed 'file1.txt.old'                  - to 'file1.txt'
PS E:\temp\dirs>

I left the mistake I made when forgetting to change the --glob from '*.txt' to '*.old' in there. It demonstrates the behavior/output when the glob doesn't match.

Example 5

Here's what's printed when there isn't a match on the files (in addition to the matches and changes):


PS E:\temp\dirs> perl .\rename.pl --subst 's/(.+)\.txt$/uc($1) . q(.txt)/ei' --glob '*.*'
'b.log' didn't change its name
Renamed 'c.txt'                          - to 'C.txt'
Renamed 'fil.txt'                        - to 'FIL.txt'
Renamed 'file1.txt'                      - to 'FILE1.txt'
'Find-Or-Remove-Empty-Dirs.ps1' didn't change its name
'rename.pl' didn't change its name
PS E:\temp\dirs>

Example 6

The --nonverbose flag causes output to be suppressed, unless it's a dry run.

PS E:\temp\dirs> dir *.txt


    Directory: E:\temp\dirs


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        27.12.2011     18:28          8 C.txt
-a---        16.12.2011     10:23       2067 FIL.txt
-a---        27.12.2011     18:28          8 FILE1.txt


PS E:\temp\dirs> perl .\rename.pl --subst 's/(.+)\.txt$/lc($1) . q(.txt)/ei' --glob '*.txt' --nonverbose
PS E:\temp\dirs> dir *.txt


    Directory: E:\temp\dirs


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        27.12.2011     18:28          8 c.txt
-a---        16.12.2011     10:23       2067 fil.txt
-a---        27.12.2011     18:28          8 file1.txt


PS E:\temp\dirs> perl .\rename.pl --subst 's/(.+)\.txt$/uc($1) . q(.txt)/ei' --glob '*.txt' --nonverbose --dry
Would rename 'c.txt'                     - to 'C.txt'
Would rename 'fil.txt'                   - to 'FIL.txt'
Would rename 'file1.txt'                 - to 'FILE1.txt'

Download

  • Rename.txt - right-click and "save as". Rename the downloaded text file to "rename.pl".
  • Rename.zip - A zip file containing a 32-bit stand-alone executable built from the Perl code in the link above. Should work on most Windows NT versions and possibly other Windows versions.