tren - Advanced File Renaming
tren.py [-1aCcbefghqtvXx] [-F file] [-l string] [-r old=new]... file|dir file|dir ...
-1 Rename only the first instance of the specified string
(Default: This is the program default)This option is provided so you can toggle the program back to its default behavior after a previous
-g
on the command line.-a Rename within the entire file or directory name
(Default: This is the program default)This option is provided so you can toggle the program back to its default behavior after a previous
-b
or-e
on the command line.-b Only perform renaming within "name" portion of file or directory name.
(Default: Rename within the entire file or directory name)Many applications use the suffix of a filename to indicate the contents or type of file. By default, tren does renaming in the entire filename including the extension. For example doing this:
tren.py -g -r eg=ug peg.jpeg
Renames the file to
pug.jpug
.. probably not what you want.The
-b
option tells tren to only perform string renaming in the actual "name portion" of the filename thereby cirumventing problems like this:tren.py -g -b -r eg=ug peg.jpeg # Renames file to pug.jpeg
-C Do case-sensitive renaming
(Default: This is the program default)This option is provided so you can toggle the program back to its default behavior after a previous
-c
on the command line.-c Collapse case when doing string substitution.
(Default: Search for string to replace is case sensitive)When looking for a match on the old string to replace, tren will ignore the case of the characters found in the filename. For example:
tren.py -c -r Old:NEW Cold.txt fOlD.txt
This renames both files to
CNEW.txt
andfNEW.txt
respectively. Notice that the new (replacement) string's case is preserved.-e Only perform renaming within "extension" portion of or directory name.
(Default: Substitute within the entire file or directory name)This option is the inverse of
-b
. It instructs tren to do the requested renaming only in the filename "extension" not on the file name portion. For example:tren.py -e -r pe=p peg.jpeg # Renames file to peg.jpg
-F file Read command line arguments from
file
It is possible to perform multiple renaming operations in one step using more than one
-r
option on the tren command line. However, this can make the command line very long and hard to read. This is especially true if the renaming strings are complex, contain regular expressions or renaming templates, or if you make heavy use of command line toggles.The
-F
option allows you to place any command line arguments in a separate file in place of- or in addition to the tren command line itself. This file is read one line at a time and the contents appended to any existing command line. You can even name the files you want renamed in the file, but they must appear as the last lines of that file (because they must appear last on the command line).Whitespace is ignored as is anything from a
#
to the end of a line:# Example replacement string file # Each line appended sequentially # to the command line -x -r t[ext]+=txt # Appended first -c -g my=Mine -X -r =/L/ -r foo=bar my.file your.file # Appended last
Note
There is one important difference between an actual command line and keeping the arguments in a file like this. Filename wildcards are not expanded within the file.
*.txt
will typicaly create a list of files ending in.txt
when given on the command line. However, the*
metacharacter has no meaning like this when used inside an arguments file.
-f Force renaming even if target file or directory name already exists.
(Default: Skip renaming if a file or directory already exists by the same name as the target.)-g Replace all instances (greedy replace) of the old string with the new.
(Default: Only the first matching string is replaced.)Ordinarily, tren only replaces the single leftmost instance of a string in the entire filename (default), the name portion (
-b
) or the extension (-e
). If you want all instances of a particular string replaced, use this option to enable "greedy" replacement:tren.py -g -r p:P pop.txp # Renames file to: PoP.txP
-h Print help information. -l string File "extension" delimiter string.
(Default: ".")tren has to know what separates the "name" from the "extension" in a filename. By default, it uses the rightmost
.
character. You can change it with this option to "divide" the filename into name and extension for renaming purposes, using any string you like. This is particularly helpful with-b
and-e
options:tren.py -b -l .long.txt -r long:short long.long.txt.long.txt.foo
This would rename the file to:
short.short.txt.long.txt.foo
Notice that tren looks for the rightmost instance of the separator to split the whole filename into name and extension components. Notice also that when you do this, no renaming of characters within the separator takes place.
-q Quiet mode, do not show progress.
(Default: Display progress)Ordinarily, tren displays what it is doing as it processes each file. If you prefer to not see this "noisy" output, use the
-q
option. Note that this does not suppress warning and error messages.This option is ignored when running in test mode (
-t
).-r Replace
old
withnew
in file or directory names.Use this option to specify which strings you want to replace in each file name. These strings are treated literally unless you also invoke the
-x
option in which caseold
is treated as a Python style regular expression.Both
old
andnew
may optionally contain Renaming Tokens described later in this document.If you need to use the
=
symbol within either the old or new string, simply escape it:\=
You can have multiple instances of this option on your tren command line:
tren.py -e old:new -e txt:doc old-old.txt
This renames the file to:
new-old.doc
By default, tren only replaces the first (leftmost) instance of the old string with the new.
-t Test mode, don't rename, just show what the program would do (ignores -q).
tren is very powerful and capable of doing nasty things to your files (like making a file disappear when another one is renamed over it). For this reason, it is helpful to test your tren commands before actually using them. With this option enabled, tren will print out diagnostic information about what your command would do, without actually doing it.
-v Print detailed program version information and exit. -X Treat the renaming strings literally
(Default: This is the program default)This option is provided so you can toggle the program back to its default behavior after a previous
-x
on the command line.-x Treat the old string in a
-r
replacement as a Python style regular expression for matching purposes.(Default: Treat the old string as literal text)
Warning
tren is a powerful file and directory renaming tool.
Be sure you know what you're about to do. If you're
not, run the program in test mode (invoke with the -t
option) to see what would happen. You have been warned!
tren is a general purpose file and directory renaming tool. Unlike
commands like mv
, tren is particularly well suited for
renaming batches of files and/or directories with a single command
line invocation. tren eliminates the tedium of having to script
simpler tools to provide higher-level renaming capabilities.
tren will not allow you to rename a file or directory if one with
the new name already exists. Such attempts will cause no change to the
file or directory being processed and a warning message will be
displayed. This is intentional to force you to manually rename or
remove the file or directory that would have been clobbered by a
rename. You can override this default and force a renaming and thus
the removal of such existing files or directories (-f
option).
tren supports a variety of renaming mechanisms. The one thing they have in common is that you must specify an old string which will be replaced by a new string when the file or directory is renamed. The general form is:
tren.py -r old=new <list of files, directories to rename>
The old
and new
string are built using a variety of
building blocks:
============================= ============================= Old Strings Are Built With: New Strings Are Built With:
-------------------------- -----------------------------
Literal Text Literal Text Regular Expressions Renaming Tokens Renaming Tokens ============================= =============================
You can use any of these building blocks alone or combine them to create expressive and powerful renaming schemes.
Literal String Substitution is just that - it replaces one literal string with another to rename the target file or directory. This is the most common, and simplest way to use tren. This is handy when you have files and directories that have a common set of characters in them you'd like to change. For instance:
tren.py -r .Jpeg=.jpg *.Jpeg
This would rename all files (or directories) whose names contained the
string .Jpeg
and replace it with .jpg
. It's important to
realize that such a substitution takes place anywhere in the file
name, not just at the end or "extension" (as it is called in Windows).
You can limit the replacement to just the "name" (-b
) or
"extension" (-e
) portions of the filename.
You may specify multiple replacement operations (-r
) on the tren
command line:
tren.py -r .Jpeg=.jpg -r old=ReallyOld *
This would rename all the files in the current directory, replacing
.Jpeg
with .jpg
and old
with ReallyOld
anywhere these
strings appeared in any of the file or directory names.
By default, only the first instance of the string is replaced in the
name, but you can use the -g
option to replace all instances of
the old string with the new one.
If you need to include the equals sign as part of the old string or
the new string literal text, you have to escape it (\=
):
tren.py -r name\=bob=name\=sally name=bob.dbms
This renames the file name=bob.dbms
to name=sally.dbms
.
Ordinarily tren treats both the old string you specify with the
-r
option literally. However, it is sometimes handy to be able
to write a regular expression to specify what you want replaced. If
you specify the -x
option, tren will treat your old string as
a Python style regex, compile it (or try to anyway!) and use it to
select which strings to replace. This makes it much easier to rename
files that have repeated characters or patterns, and groups of files
that have similar, but not idential strings in their names you'd like
to replace.
Say you have a set of files that are similar, but not idential in name, and you want to rename them all:
sbbs-1.txt
sbbbs-2.txt
sbbbbbbbbs-3.txt
Suppose you want to rename them, replacing two or more instances of
b
with X
. It is tedious to have to write a separate literal
-r old:new
string substitution for each instance above. This is
where regular expressions can come in handy. When you invoke the
-x
option, tren understands this to mean that the old
portion of the replacement option is to be treated as a Python style
regular expression. That way, a single string can be used to match
many cases:
tren.py -x -r bb+:X *.txt
This renames the files to:
sXs-1.txt
sXs-2.txt
sXs-3.txt
Keep in mind that a literal string is a subset of a regular
expression. This effectively means that with -x
processing
enabled you can include both regular expressions and literal text in
your "old string" specification. The only requirement is that the
string taken as a whole must be a valid Python regular expression. If
it is not, tren will display an error message to that effect.
Because Python regular expressions can make use of the =
symbol,
you need a way to distinguish between an =
used in a regular
exression and the same symbol used to separate the old and new
operands for the -r
option. Where this symbol needs to appear in
a regular expression, it has to be escaped like this: \=
.
tren implements the notion of Renaming Tokens. These can
appear in either the old- or the new string components of a -r
renaming argument.
It is sometimes useful to be able to take a group of files or directories whose names have nothing in common and impose a common naming scheme on them. Another use for renaming tokens is to do the renaming based on some property the file or directory possesses like its creation date, size, owner's name, and so on.
In their simplest form, renaming tokens are nothing more than
"canned" information tren knows about a particular file or
directory. For instance, if you insert the /D/
token into a
old- or new string definition, tren will replace it with the
creation date of the file or directory being renamed and use that
string in the renaming process.
There are also tokens that allow you to use system information in your renaming strings. Finally, there are tokens that can be used to automatically renumber or sequence (order) a set of files or directories being renamed.
For example, suppose you and your friends pool your vacation photos but each of your cameras uses a slightly different naming scheme. You might want to just reorder them by the date and time each picture was taken, for example. That way you end up with one coherent set of named and numbered files. You might start with something like this:
DSC002.jpg # Bob's camera, taken 1-5-2010 at noon
dc0234.Jpg # Mary's camera, taken 1-5-2010 at 8am
032344.jpeg # Sid's camera, taken 1-3-2010 at 4pm
It would be nice to get these in order somehow:
tren.py -r =/D/-MyVacation-/+T0001/.jpeg *.jp*
This would rename all the files in the current directory ending with
.jp*
. The /D/
would be replaced with the date the picture
was taken. The /+T0001/
refers to a starting sequence number to
uniquely identify pictures taken on the same date. The other strings,
-MyVacation-
and .jpeg
, are inserted literally in the final
file names. After we ran this command, the files above would end up
with these names:
20100103-MyVacation-0001.jpeg # Sid's
20100105-MyVacation-0001.jpeg # Mary's
20100105-MyVacation-0002.jpeg # Bob's
Notice that the files taken on the same date have been sequenced by
the time-of-day they were taken because we included the /+T0001/
renaming token in our pattern. The +
here means to construct
the sequence in ascending order. A -
would specify
descending order.
Note
Notice that there is no old string in our example above.
That is, there is nothing to the left of the =
symbol in
the -r
option. This effectively means "replace
everything" in the existing file or directory name. You can
do the same thing using a regular expression:
tren.py -x -r *=/D/-MyVacation-/+T001/.jpeg *.jp*
Of course, if you use the -b
or -e
flags, you limit
just what portion of the filename is considered
"everything".
Of course, you don't have to replace the entire filename when using tokens. It's perfectly legitimate to replace only a portion of the existing name:
tren.py -r file=/D/-file file-1 file.2
This would rename our files to: 20100101-file-1 and
20100101-file.2
Notice that we combined literal text and a renaming
token to do this.
You can even use renaming tokens in your old string specification. For instance, suppose you manage a number of different systems and you set their system name in an environment variable called SYSNAME. You might then do something like this:
tren.py -x -r /$SYSNAME/*.bku=/$SYSNAME/*.bku.old
If your system name was "matrix", then the command above would only
rename files whose names began with matrix
and ended with .bku
.
If your system name were "morton", then the command above would only
rename files whose names began with morton
and ended with .bku
.
There are a couple of things to keep in mind when doing things like this:
- The
/$SYSNAME/
in the old string is used to find the text to rename, whereas the same renaming token in the new string means insert the contents of that environment variable here.- Renaming tokens are always evaluated before any regular expression processing takes place. It's up to you to make sure that when the two are combined (as we have in the example above), that the final result is still a valid Python regular expression. This may involve explicit quoting of the renaming tokens used in the old string specification.
tren has many other kinds of renaming tokens. Their structure and use is described in some detail in the next section.
tren defaults a specific set of behaviors:
old
andnew
renaming text is treated literally- Renaming takes place within the entire filename
- Only the first instance of
old
is replaced withnew
- Renaming is case sensitive
There are command line "switches" to override each of these defaults
(-x
, -b
, -e
, -g
, and -c
).
There are additional "switches" to return the program to its
default behavior (-X
, -a
, -1
, and -C
).
The idea is that you can specify what kind of replacement behavior you want for each different renaming operation. For instance:
tren.py -e -r txt=TXT -g -a -c -r M=0 -C -x -r [ss]+=S filelist
This would rename the files as follows:
- The first instance of
txt
would be replaced withTXT
in each of the file extensions.- All instances of
m
orM
would be replaced anywhere they were found in the filename.- All instances of one or more strings in the form
ss
would be replaced withS
.
It's important to understand some subtleties of just how tren works, particularly if you intend to create complex, multi-replacement command lines:
- Command line processing is from left to right. As we saw in the COMMAND LINE TOGGLES above, this means the options can be different for each renaming operating you specify.
- Regular expression processing is unaffected by the
-g / -1
(greedy replace) and-c / -C
(ignore case) options. That's because there are regular expression mechanisms for achieving the same thing. More importantly, if you've selected regular expression matching, it's probably because you want very fine grained control of the renaming defined by the regex. In short, regular expression matching always takes place on the original characters of the target portion of the name and does replacement as called for in the regex itself.- tren processes each renaming string in the following manner:
- Select the target portion of the filename for renaming (all, name only, extension only).
- Replace all renaming tokens with their equivalent text in both the
old
andnew
renaming strings.- If
-c
is in effect, collapse the target and theold
renaming string to lower case before checking for a match.- Replace the first- (default and
-1
) or all (-g
) instances ofold
withnew
.
As we've just seen, a Renaming Token is nothing more than a string representing something tren knows about one of three things:
- An attribute of the file or directory being renamed
- An attribute of the underling operating system environment
- A sequence that reflects some ordering principle
Renaming tokens are delimited by the /
character. tren
replaces these tokens with the corresponding information (see
descriptions below) wherever you indicated in either the old
or
new
strings of a -r
rename command.
Currently, tren defines a number of renaming tokens. Future releases of tren may add more of these, so it's good to periodically reread this material.
These tokens are derived from information about the file or directory being renamed.
/D/ File or directory creation date
This token is replaced with the date of creation
of the file or directory being renamed. It is
in yyyymmdd
format.
/E/ Original File Extension
This token is replaced the "extension" portion of the file or directory before renaming. This does not include the extension separator string.
/F/ Original File Name
This token is replaced the "name" portion of the file or directory before renaming.
Note
Notice that there is no token for the whole filename
because you can always synthesize it with /F/./E/
/G/ File or directory primary group name
This token is replaced with the name of the primary group to which the file belongs.
/I/ File or directory creation date in ISO format
This token is replaced with the date of creation of the file or directory being renamed. It is similar to/D/
except it is in ISO format,YYYY-MM-YY
.
/L/ File or directory length
This token is replaced with a numeric string that indicates the length of the file or directory in bytes.
/T/ File or directory creation time
This token is replaced with the time of creation
of the file or directory being renamed. It is
in hh:mm:ss
format.
/U/ File or directory owner name
This token is replaced with the name of the file or directory's owner.
/d/ File or directory day of creation
This token is replaced with the the day of the month the
file was created in dd
format.
/h / File or directory hour of creation
This token is replaced with the hour the file was
created in hh
format.
/m/ File or directory minutes of creation
This token is replaced with the minutes the file was
created in mm
format.
/o/ File or directory month of creation
This token is replaced with the numeric month the file was
created in mm
format.
/ooo/ File or directory month of creation
This token is replaced with the abbreviated name of the
month the file was created in Mmm
format.
/s/ File or directory seconds of creation
This token is replaced with the seconds the file was
created in ss
format.
/y/ File or directory year of creation
This token is replaced with the year the file was
created in yyyy
format.
These tokens are derived from the underlying operating system and runtime environment.
/$ENV/ Environment variable
This token is replaced with the value of the environment variable
$ENV
. If that variable does not exist, the token is replaced with an empty string:tren.py -r =/$ORGANZATION/-/F/./E/ *
This prepends the organization's name to everything in the current directory.
/`cmd`/ Arbitrary command execution
This token is replaced with the text returned by executing the
cmd
command.For instance, you might want to prepend the name of the system to a all you shell scripts:
tren.py -r =/`uname -n`/-/F/./E/ *.sh
This construct is more generally a way to synthesize renaming tokens that are not built into tren. For instance, the built-in tokens only provide information about file and directory creation dates. You might want to use the date of last access. You do this by writing the appropriate script or program and then executing it within the /`cmd`/ construct. This effectively provides tren an unlimited number of renaming tokens.
Warning
Be very careful using this. It's possible to construct bizzarre, overly long, and just plain chowder-headed strings that make no sense in a renaming context using this construct.
Sometimes it's useful to rename files or directories based on some
property they possess like the date or time of creation, the size of
the file, who owns it, and so on. That's the idea behind the /D/
,
/T/
, and /S/
renaming tokens described in the previous section.
An extension of this idea is to order all the files being renamed based on one of these parameters. For instance, instead of actually embedding the date and time of creation in a file or directory name, you might want to order the files from oldest to newest with a naming convention like:
file-1.txt
file-2.txt
file-3.txt
This guarantees uniqueness in the final name and also sees to it that a sorted directory listing will show you the files or directories in the order you care about.
This is the purpose of sequence renaming tokens. They give you various ways to create sequences that can be embedded in the final file or directory name.
Sequence renaming tokens consist of three descriptive components and have the following general format:
/<ordering flag><type><counting pattern>/
where,
ordering flag:
+ ascending
- descending
type:
D sequence on file creation date & time
L sequence on file length
R sequence on the command line file order
T sequence on file creation time within a given day
The counting pattern is used to specify two things: The width of the sequence string, and the starting value for the sequence. Examples:
0001 -> 0001, 0002, 0003, ...
0000 -> 0000, 0001, 0002, ...
03 -> 03, 04, 05, ...
You do not have to use a 0
to indicate the sequence width. You
can use any padding characters you like. tren only cares about
the width of the field and will "consume" your padding characters as
the count increases.:
xxx3 -> xxx3, xxx4, xxx5, ... 9999, xxx3, xxx4, ...
-+8 -> -+8, -+9, -10, -11, ... 999, -+8, -+9, ...
You are not restricted to numbers in a counting pattern. Letters may also be used. tren will preserve the case you specify in the token when creating sequences like this:
000a -> 000a, 000b, 000c, ... zzzz, 000a, ...
---Y -> ---Y, ---Z, --AA, ... ZZZZ, ---Y, ---Z, ...
Notice that when a sequence "rolls over", the next value is the initial sequence value you specified.
Sequence renaming tokens are thus a way to generate an ordering based on some property common to everything being renamed. Keep in mind that for purposes of sequencing, tren makes no distinction between a file and directory. It merely sequences based on the property you requested.
tren currently supports the following kinds of sequencing:
/+D0001/ Sequence based on the creation date/time
This produces a sequence from oldest to newest (or the reverse) of the renamed objects.
tren.py -b -r =/+D0002/ *.txt
This would rename all the files in the current directory into the form,
0002.txt
,0003.txt
, ...9999.txt
with0002.txt
being the oldest file and9999.txt
being the newest. If you used the token/-D0002/
, you'd get the same thing, but in reverse order.
/+L0001/ Sequence based on the size of the files being renamed
This produces a sequence from shortest to longest (or the reverse) of the renamed objects.
tren.py -r /+L0002/ *.txt
This would rename all the files in the current directory into the form,
0002.txt
,0003.txt
, ...9999.txt
with0002.txt
being the shortest file and9999.txt
being the longest. If you used the token/-L0002/
, you'd get the same thing, but in reverse order.
/+R0001/ Sequence based on the file order on the command line
This produces a sequence based on the order (or the reverse) of renaming - i.e., The order of the names on the command line.
tren.py -e -r =/+R0000/ MyFile.txt AFile.jpg me.log
This would rename all the files to,
MyFile.0
,AFile.1
, andme.2
. If you used/-R0000/
, you'd getMyFile.2
,AFile.1`
, andme.0
.
/+T0001/ Sequence based on creation time within date
This produces a sequence based on the creation date and time similar to the
/+D.../
sequence renaming token above. However, the sequence resets at the beginning of each new date. This allows you to create unique sequences within a date like our example of renaming photo files from different cameras. (See: An Overview Of Renaming Tokens):tren.py -b -r =/D/-/+T0100/ *.txt
This would rename all the
.txt
files in the current directory into the form:200103010-0100.txt 200103010-0101.txt 200103010-0102.txt 200104010-0100.txt 200104010-0101.txt 200104010-0102.txt 200104011-0100.txt 200104011-0101.txt 200104011-0102.txt ...
In other words, instead of sequence just on the creation date, this allows us to sequence within the date. As always, the
-
flag will reverse this order within the date.Notice that you can get something similar using just file attribute renaming tokens:
tren.py -b -r =/D/-/T/ *.txt
This would produce names in the form:
200103010-03:01:23.txt 200103010-03:01:24.txt 200103010-03:01:25.txt ...
For most purposes, though, the order, rather than the absolute time is both more useful and more readable.
Here are some common examples of tren in action - the resulting file name(s) shown to the right as a comment. Study each example carefully. Small subtleties are introduced in various adjacent examples to illustrate different features of tren:
Get help:
tren.py -h
Print out detailed version information:
tren.py -v
Simple rename:
tren.py -r old=New fold.txt log.old # fNew.txt log.New
Change file "name":
tren.py -b -r old=New fold.txt log.old # fNew.txt log.old
Change file "extension":
tren.py -e -r old=New fold.txt log.old # fold.txt log.New
Rename all instances of a given string:
tren.py -g -r bin=Bin binary_bin.binbin # Binary_Bin.BinBin
Rename, ignoring case:
tren.py -c -r bin=BIN Binary_bIN.txt # BINary_bIN.txt
Rename multiple strings at once:
tren.py -r log:txt -r New:old New.log # old.txt
Rename using regular expressions:
tren.py -x -r a+=a Saaaaaaaally.doc # Sally.doc
Rename a file containing the
=
symbol:tren.py -r a\=b=c\=d a=b.txt # c=d.txt
Use renaming token:
tren.py -r =/I/ file.1 # 2010-01-12
Use renaming token to change file "name":
tren.py -b -r =/I/ file.1 file.2 # 2010-01-12.1 2010-01-12.2
Use renaming token to change file "extension":
tren.py -e -r =/D/ file.1 # file.20100112
You must have a reasonably current version of Python installed.
On windows platforms, the /U/
and /G/
renaming tokens return
winuser
and wingroup
respectively. They do not return the
underlying operating system ownership information.
tren is Copyright (c) 2010 TundraWare Inc.
For terms of use, see the tren-license.txt
file in the
program distribution. If you install tren on a FreeBSD
system using the 'ports' mechanism, you will also find this file in
/usr/local/share/doc/tren
.
Tim Daneliuk
tren@tundraware.com
$Id: tren.rst,v 1.130 2010/01/20 22:26:26 tundra Exp $
You can find the latest version of this program at:
http://www.tundraware.com/Software/tren