Bulk rename utility


Bulk Rename Utility written in C++. Files and directories can be passed as command line arguments to rename them in bulk according to some naming scheme (Name String). If any file or directory path is not passed as command line argument, it will wait for user to type the path i.e it will take the path from standard input (>=version 3.0.1). It uses C++ regex (ECMAScript regex) as the default regex to provide search (and replace) functionality, other regex modes are available through (-re) option. It provides an undo functionality too to move back an unwanted rename operation. You can also run a simulation instead of actual rename to view the potential outcome as program output on terminal with the -sim option.


  1. Renames files or directories in bulk.
  2. Undo functionality (rnm -u).
  3. Names can be modified by performing regex replace. It enables generating new names by deleting/appending/modifying part of the old filename. It also enables easy conversion from lowercase to uppercase and vice-versa.
  4. Lowercase-Uppercase conversion is selective i.e you can apply case conversion in part of the name at a targeted position.
  5. Names can be modified with certain predefined rules. For example, you can insert parent directory name or working directory name or index etc... in filename in arbitrary positions.
  6. Names can be taken from a file, and these names can also be modified by applying Name String rules on them.
  7. Search functionality. It uses the ECMAScript regex by default. Regex mode can be changed (POSIX basic, extended, egrep, grep, awk, ECMAScript). Fixed string search is also possible.
  8. Null terminated file support for file names (Null termination is a good way to store filenames in a file).
  9. Sort functionality. Available sorting methods are: Natural sort and general alphabetical sort.
  10. Multiple search criteria and replacement methods are possible.
  11. Search keywords and replacement regex can also be supplied form files (single or multiple).


  • libstdc++6 (>=4.9.2)


Unix (32 or 64 bit):

Make sure libstdc++6 (>=4.9.2) or GCC (g++>=4.9.2) is available in your system.

  1. Give the install file execution permission (chmod +x install) and
  2. Run it or just drag and dropt it on terminal and hit Enter (requires root privilege).

The install script depends on Bash Shell. If you don't have bash installed, then just copy the suitable binary file (rnm) from bin/x32 or bin/x64 directory to /usr/bin directory, and copy the rnm.1 file to /usr/share/man/man1 directory.


Aside from the above generalized method, you can also install it in Ubuntu from PPA (ppa:neurobin/ppa).

sudo add-apt-repository -y ppa:neurobin/ppa
sudo apt-get update
sudo apt-get install rnm

If you are in Ubuntu 14.04 or 12.04 (trusty or precise), you will need to add ubuntu-toolchain repository to make libstdc++6 (>=4.9.2) available:

sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo add-apt-repository -y ppa:neurobin/ppa
sudo apt-get update
sudo apt-get install rnm


  1. Give the uninstall file execution permission and
  2. Run it or just drag and dropt it on terminal and hit Enter (requires root privilege).


rnm directory/file/path -ns new_name [other options]
rnm directory/file/path -rs "/search regex/replace string/gi" [other_options]
rnm directory/file/path -nsf namestring/file/path

One of the options of -ns or -nsf or -rs is mandatory. Options are not sequential, their position in the argument list have no significance. For example, rnm filepath -ns name is the same as rnm -ns name filepath. Though passing the Directory/File path at the end of the argument list is considered to be safe and wise.

Options are case insensitive, i.e -ssF and -ssf are the same.


-h, --help : Show help menu.

--index, --start-index, -i,-si : Starting index.

--end-index, -ei : End index i.e index to stop renaming from. It is only for files inside a directory that is being recursively taken due to a depth value greater than 0, i.e it works on directory index. Note that directory index /id/ will renew in each directory i.e in each directory rename will be performed from start index to end index.

--increment-value, -inc : Increment value (floating point decimal). The amount, index will be incremented or decremented in each iteration. Decremented index is available through name string rule: /-i/, /-id/ etc..

--line-increment-value, -linc : The amount line count will be incremented or decremented in each iteration. This is always a positive integer.

-ifl : Index field length. Non occupied field will be filled with index field fillers (set with -iff). iff is set to the character 0 by default.

--index-field-filler, -iff : Not occupied field in index will be filled with a character which is set by this option.

--index-field-precision, -ifp : Index is a floating point decimal value. This sets the precision i.e the number of digits that should be taken after the decimal point.

--name-string, -ns : Name string.

--name-string-file, -ns/f : Name string file. File containing name string (one per line). -nsf /hist/ i.e a value passed /hist/ as Name string file, will try to take the file from history.

--name-string-file-null-terminated, -ns/fn : Name String file. This takes a null terminated Name String file, i.e filenames are terminated by null character (\0) instead of new line (\n).

--line, --start-line, -l, -sl : Start Line number in name string file.

--line-reverse, --start-line-reverse, -lv, -slv : Same as -l or -sl, except line number will be decremented in each iteration.

--end-line, -el : End line number. Line number to stop renaming from.

--end-line-reverse, -elv : Same as -el, except line number will be decremented in each iteration.

--search-string, -ss : Search string. String that will be used to search for files with matching names. This is generally a regex if not passed with -ssf option.

--search-string-file, -ss/f : Search string file. A file containing search string per line.

--search-string-fixed, -ssf : Fixed search string (not treated as regex).

--search-string-fixed-file, -ssf/f : Search string file. Contains fixed search string per line.

--replace-string, -rs : Replace string. A string in the form /search_string/replace_string/modifier. See Replace String in Terminology for details.

--replace-string-file, -rs/f : Replace string file. A file containing replace string per line.

--regex, -re : regex mode. Available regex modes are POSIX compliant basic & extended regex, regex used by grep, awk, egrep and the default regex is ECMAScript regex. For example, to have a grep like regex, pass the option -re grep, to use POSIX compliant extended regex, pass -re extended

--regex-locale, -rel : If this is passed as argument, regex will follow Locale. that is regex like [a-z] will have their meaning according to the system locale.

--depth, -dp : Depth of folder. -1(any negative number) means unlimited depth i.e all files and subdirectories will be included. Other values may be 0 1 2 3 etc... Default depth is 0, i.e directory contents will be ignored.

--file-only, -fo : File only mode. Only files are renamed (not directory). Goes to subdirectory/s if depth (-dp) is set to 1 or greater. Default depth is set to 0.

--directory-only, -do : Apply rename on directory only.

--exclude-directory, -ed : Apply rename on files only, exclude any and all directory and their contents. This option is equivalent to file only mode with a zero (0) depth value.

--count-directory, -cd : Count directory in reserved index, regardless of other options. Reserves indices for directories even if it is File Only mode.

--count-file, -cf : Count file in reserved index, regardless of other options. Reserves indices for files even if it is Directory Only mode.

--sort, -s : Sort files in natural order (Human perceivable order). This option can be modified to use other sorting methods. For example: -s/g or --sort/g will sort the file in general (alphabetical) order. Other options are -s/n (Natural sort), -s/none (No sort).

-y : Confirm Yes to all.

-u, -U, --undo : Undo renaming

--force, -f : Force rename. Enables renaming some restricted files except / and the program itself.

-v : Version info.

-q : Quiet operation.

-- : If this option is passed, anything and everything after it will be taken as file path. Put all options before passing this option.

--show-options, -shop : This shows an info about the various options passed as arguments and how they are being treated behind the scene.

--simulation, -sim : This runs a simulation of rename instead of actual rename operation, and prints all kinds of available outputs. -q option won't have any effect if this option is passed.

Technical Terms:

Reserved Index : Index will be incremented even if any file is skipped renaming in order to reserve the index for that skipped file

Reverse Index : Decrementing index.

Name String : A string, that is parsed to create names for new files. It can be fixed name which then can be modified for different files at runtime. Name sting is parsed by the following rules (must be wrapped around with filepath delimiter /):

  1. /i/ in name string will be replaced with index.
  2. /ir/ in name string will be replaced with reserved index.
  3. /id/ in name string will be replaced with directory index (index inside a directory).
  4. /idr/ in name string will be replaced with reserved directory index
  5. /-i/ in name string will be replaced with inverse index.
  6. /-ir/ in name string will be replaced with inverse reserved index. In general, -i in the above replacement rules (applies to indexes excluding line indexes) will mean inverse index conforming to their meaning.
  7. /dc/ in name string will be replaced with directory count
  8. /l/ in name string will be replaced with line number from Name String File.
  9. /la/ in name string will be replaced with actual line number from Name String File.
  10. /n/ in name string will be replaced with filename without extension. If used with -nsf option, the filename will be the name taken from the Name String File.
  11. /fn/ in name string will be replaced with full name of the files. If used with -nsf option, full name will be the name taken from the Name String File.
  12. /rn/ in name string will be replaced with Replaced Name.
  13. /pd/ in name string will be replaced with parent directory name of the current file or directory.
  14. /wd/ in name string will be replaced with the current working directory name.

Name String File : A file which contains a list of name string (one per line). Empty lines will be ignored and line number won't be counted. Actual line number (which counts the empty lines too) is available through name string rule : /la/.

Search String : A string that is used to search for files with matching filenames against the search string. By default it is a regex if -ssF option is not used.It is generally in the form /regex/modifier , where regex is the regex to search for and available modifier is i which implies case insensitive search. If no modifier is used, the regex format can be reduced to /regex/ or simply regex.

Terminate search strings (/regex/ fromat only) with ; to provide multiple search strings, e.g '/s1/i;/s2/;/s3/'. This applies to fixed search strings as well.

Also you can provide multiple search strings with repeated -ss and/or -ssf options and files with repeated -ss/f and/or -ssf/f options. These options can be mixed with each other too.

Index Field Length: An integer value defining the field length of index. By default empty field will be filled with 0's. For example, if the value is 3, then index will be 001, 002, 003, etc.. Different filler (other than 0) can be provided with the -iff option.

Replaced Name : The name can be modified at runtime using replace string. replace string will be parsed to create a new Name String rule: /rn/ which can be used in Name String. If name string is not passed as argument, the new name of the file will be /rn/. Replaced Name is always generated from the old filename.

Replace String : Replace String is a regex of the form: /search_part/replace_part/modifier where search_part is the regex to search for and replace_part is the string to replace with. Name String rules are avalilable in search_part and replace_part in Replace String. Regarding replace string, there are several special cases:

  1. & will be taken as the entire match found by the regex (search_part).
  2. \1, \2 etc.. is the back-references, i.e you can access captured groups with these back-references. If you want to isolate a back-reference make it fill up the two digit limit or wrap it around with {}. For example, if you want to put a digit (2) after back-reference \1, you can't use it like \12. \12 will mean 12th back-reference not \1 appended with a digit (1). In this case either use \01 instead of \1 or isolate the back-reference with {} i.e \{1}.
  3. \c will convert the matched string to lowercase, and \C will convert it to uppercase. No other character is allowed in replace part if this is used. You can still concatenate different replace strings with ;.
  4. \p is the prefix (i.e., the part of the target sequence that precedes the match)
  5. \s is the suffix (i.e., the part of the target sequence that follows the match).

to insert a & literally, use \& and for \ use \\.Two modifiers are available: g and i. g stands for global and replaces every instances of match found. i stands case insensitive search (default is case sensitive).Replace String is always performed on old file name.

Terminate replace strings with ; to provide multiple replace strings, e.g '/s1/r1/gi;/s2/r2/i;/s3/r3/'.

You can provide multiple replace strings with repeated -rs option and multiple file with repeated -rs/f options. These options can be mixed with each other too.

Example: '/video/Episode /i//gi' will replace every instances
of 'video' with 'Episode index' i.e you will get new rname as:.
Episode 1..., Episode 2..., etc...

Regex : Supported regexes are POSIX compliant basic & extended regex, grep, egrep and awk type regexes and the default ECMAScript Regex. You can change the regex mode with -re or --regex option.

Only invalid characters for a file or directory name is the path delimiter and the null character (\0).


rnm file -ns new_file
rnm file -rs "/f/F/"                             ( will replace f with F in the name, i.e new name will be: File)
rnm folder -ns "New Folder" -do                  (-do forces Directory only mode)
rnm ./New*/* -ns /i/.ext                         (globbing is allowed)
rnm ./New*/* -ns /i/.ext -ed                     (-ed forces file only mode)
rnm "./New Folder" -ns /id//dc/.ext -dp 1 -fo    (This will go inside the New Folder directory)
rnm ./New* -ns /id/.ext -ss "regex"
rnm -nsf filepath -ns /n//id/.ext
rnm -nsf filepath

Things to care:

  1. All options should always be separated by space. For Example: -vy won't mean two option -v and -y, rather it will mean a single option -vy.
  2. Any non option argument will be treated as file or directory path. For example in
    rnm file1 file2 -- -ns fd
    file1, file2 and -- will be taken as file paths.
  3. Be wary of filename globbing. Command like rnm ./* will take all files and directories as arguments and thus the files and directories will be subject to rename operation. If you don't want to rename directories, use file only mode (-fo). If you want to go inside directories, use depth (-dp) greater than 0 with file only mode.
  4. If you run rnm . -ns something or rnm ./ -ns something, your current directory will be renamed (be careful).
  5. This is a dangerous tool like rm, so use with care. If you make a mistake and do some unwanted rename, run rnm -u to undo (before running any more rnm command).
  6. Pass all regex like strings within quotes even if they don't contain any white space.
  7. To pass a filename that resembles an option, use ./, i.e ./-ns to pass a file named -ns in the current directory. Or you can use the -- option make it a non-option argument; in that case make sure to pass all "Option" arguments before --, because everything after -- will be taken as file path/s.
  8. Pass file or directory path list at the end of the argument sequence. Use -- to make all the arguments after it as paths (not options).


1.0.0: Sat 14 Aug 2015

Birth of rnm

2.0.0: Sun Aug 9 23:18:00 BDT 2015

  1. Added undo feature.
  2. Added end index feature and end line number feature.
  3. Added inverse index feature
  4. Added new name string rules for inverse index.
  5. Added /hist/ as a valid argument for -nsf option to take Name String File from history.
  6. Logging functionality. Log files are put in $HOME/.neurobin/rnm
  7. Lots of bug fixes.

2.0.1: Wed Aug 12 02:36:00 BDT 2015

  1. Added name modification feature using sed.
  2. Added extra Name String Rule /smn/ or /rn/.

3.0.0: Fri Aug 21 12:33:49 BDT 2015

  1. Code rewritten in C++.
  2. Shell independent.
  3. Portable.
  4. Supports all characters allowed in file/directory name according to POSIX specs.
  5. Regex syntax changed to ECMAScript Regex.
  6. -rs option added.
  7. -iff option added.
  8. -ifp option added.
  9. -inc option added.
  10. -linc option added.
  11. Renamed option -li to -lv and -eli to -elv.
  12. -shop and -sim (simulation) option added.
  13. New name string rule: /la/ added.
  14. Removed -f (force rename) option.

3.0.1: Sat Aug 22 21:28:14 BDT 2015

  1. rnm now can take file or directory name from standard input, i.e if you run rnm without any file or directory path, it will wait for you to type it.
  2. --force or -f i.e force rename option is back. It will enable some restricted files or directories to be renamed except the root filesystem (/).
  3. You no longer need confirmation for renaming single file or directory.

3.0.2: Mon Aug 24 17:01:25 BDT 2015

  1. Added POSIX compliant basic and extended regex mode.
  2. Added awk, grep and egrep like regex mode.
  3. Added system locale support in regex.

3.0.3: Mon Aug 24 17:01:25 BDT 2015

Bug fix: inconsistency in reserved directory index.

3.0.4: Tue Sep 8 14:04:26 UTC 2015

  1. New Name String rule: /pd/ for parent directory, /wd/ for working directory.
  2. /regex/ can be wrtten as regex if no modifier is passed.
  3. Directory index bug fixed.

3.0.5: Sat Sep 19 13:00:59 UTC 2015

  1. -- option added. Anything after this option will be taken as file path.
  2. Added warning for multiple defintion of the same option i.e option override.

3.0.6: Sun Sep 20 16:45:37 UTC 2015

  1. Directory reserved index inconsistency fixed.
  2. Added -cd and -cf options.
  3. Added sort functionality. -s for default (natural) sort, -s/g for general sort. -s/n for natural sort. -s/none for no sort.

3.1.0: Thu Oct 15 00:04:43 UTC 2015

  1. Multiple search string support added.
  2. Multiple replace string support added.
  3. Search strings can be taken from a file.
  4. Replace strings can be taken from a file.

3.1.1: Thu Oct 15 13:14:24 UTC 2015

  1. Multiple search strings or files can now be provided by repeating options.
  2. Multiple replace strings or files can now be provided by repeating options.
  3. Multiple file support for replace string and search string.
  4. Status of skipping files due to existing files with same names is changed to Warning from Error.

3.1.2: Thu Oct 15 17:43:05 UTC 2015

  1. \c and \C is added in replace string rules (used in replace_part) for lowercase-uppercase conversion.

3.1.3: Thu Oct 29 11:25:15 UTC 2015

  1. Fix suffix in regex replace in replace string.
  2. Fix index field precision.
  3. Added back-reference isolation with {} i.e \{12}, \{1} etc..

3.2.0: Mon Nov 02 18:10:26 UTC 2015

  1. Directories can be renamed recursively in subdirectories.
  2. Potential bug fixes.
  3. -nsf and -nsfn option is removed. Use -ns/f or -ns/fn instead.

3.2.1: Tue Nov 3 09:19:46 UTC 2015

  1. Natural sort algorithm improved/fixed.


If you are a developer, you can consider contributing to this project by forking this repository and making changes for better and do a pull request, or sharing ideas and suggestions or finding bugs, anything at all, what you think will be beneficial for this project.

If you aren't a developer, but still want to contribute, then you can support the contributing developers spiritually, by starring the repository and sharing ideas. If you want to be notified of the continuous development, you can add this in your watch list in Github.

If you see any problems or bugs please open an issue here