- Rename files and directories recursively under ubuntu /bash
- 8 Answers 8
- How to Rename a Directory in Linux
- Renaming Directories With the mv Command
- Renaming Directories With the rename Command
- Renaming a Single Directory With the rename Command
- Renaming Multiple Directories With the rename Command
- Renaming Directories With the find Command
- Renaming Directories With Bash Scripts
Rename files and directories recursively under ubuntu /bash
I want to rename all files and directories that contain the word «special» to «regular». It should maintain case sensitivity so «Special» won’t become «regular». How can i do this in bash recursively?
8 Answers 8
find /your/target/path/ -type f -exec rename 's/special/regular/' '<>' \;
To rename directories only:
find /your/target/path/ -type d -execdir rename 's/special/regular/' '<>' \+
To rename both files and directories:
find /your/target/path/ -execdir rename 's/special/regular/' '<>' \+
@speakr, Great solution, thanks! Could you provide more details about what it is doing, especially this part » ‘<>‘ \ «? Quick goggling did not help, so I thought that this information may be useful for others as well.
@ThiloSchulz It does, but you have to use find … -execdir … ‘<>‘ + instead of … ‘<>‘ \; . Clarification added.
In case of many files, take advantage of regex in find, for the last example above you use: find /your/target/path/ -regex ‘.*special.*’ -execdir rename ‘s/special/regular/’ ‘<>‘ \+ , otherwise it will be quite slow!
Try doing this (require bash —version >= 4):
shopt -s globstar rename -n 's/special/regular/' **
Remove the -n switch when your tests are OK
There are other tools with the same name which may or may not be able to do this, so be careful.
If you run the following command ( GNU )
$ file "$(readlink -f "$(type -p rename)")"
and you have a result like
. /rename: Perl script, ASCII text executable
then this seems to be the right tool =)
If not, to make it the default (usually already the case) on Debian and derivative like Ubuntu :
$ sudo update-alternatives --set rename /path/to/rename
(replace /path/to/rename to the path of your perl’s rename command.
If you don’t have this command, search your package manager to install it or do it manually
Last but not least, this tool was originally written by Larry Wall, the Perl’s dad.
I have about 1700 files to rename in directories in my home directory. That seems too many for this to work, that actually was the text in the error message, too many arguments.
People trying to rename a pattern occuring multiple times in the same name should add the ‘g’ flag at the end of the substitution command: ‘s/old/new/g’
If you don’t mind installing another tool, then you can use rnm:
rnm -rs '/special/regular/g' -dp -1 *
It will go through all directories/sub-directories (because of -dp -1 ) and replace special with regular in their names.
@LokMac : I don’t think it’s available in homebrew (I only package binary for debian based OS), If you have automake, you can install it in any Unix system (Instructions are in the readme).
If using -execdir to transform both files and directories, you’ll also want to remove -type f from the example shown. To spell it out, use:
find /your/target/path/ -execdir rename ‘s/special/regular/’ ‘<>‘ \+
Also, consider adding g (global) flag to the regex if you want to replace all occurrences of special with regular in a given filename and not just the first occurrence. For example:
find /your/target/path/ -execdir rename ‘s/special/regular/g’ ‘<>‘ \+
will transform special-special.jpg to regular-regular.jpg . Without the global flag, you’ll end up with regular-special.jpg .
FYI: GNU Rename is not installed by default on Mac OSX. If you are using the Homebrew package manager, brew install rename will remedy this.
Here is another approach which is more portable and does not rely on the rename command (since it may require different parameters depending on the distros).
It renames files and directories recursively:
find . -depth -name "*special*" | \ while IFS= read -r ent; do mv $ent $regular$; done
What it does
- use find with -depth parameter to reorder the results by performing a depth-first traversal (i.e. all entries in a directory are displayed before the directory itself).
- do pattern substitutions to only modifiy the last occurence of regular in the path.
That way the files are modified first and then each parent directory.
Giving the following tree:
├── aa-special-aa │ └── bb-special │ ├── special-cc │ ├── special-dd │ └── Special-ee └── special-00
It generate those mv commands in that particular order:
mv ./aa-special-aa/bb-special/special-cc ./aa-special-aa/bb-special/regular-cc mv ./aa-special-aa/bb-special/special-dd ./aa-special-aa/bb-special/regular-dd mv ./aa-special-aa/bb-special ./aa-special-aa/bb-regular mv ./aa-special-aa ./aa-regular-aa mv ./special-00 ./regular-00
To obtain the following tree:
├── aa-regular-aa │ └── bb-regular │ ├── regular-cc │ ├── regular-dd │ └── Special-ee └── regular-00
As mentioned by Rui Seixas Monteiro it’s best to use the -iregex pattern option with the Find command. I’ve found the following works and includes the global flag in the regex as mentioned by U007D:
find /path/ -type f -iregex '.*special.*' -execdir rename 's/special/regular/g' '<>' \+;
find /path/ -type d -iregex '.*special.*' -execdir rename 's/special/regular/g' '<>' \+;
find /path/ -iregex '.*special.*' -execdir rename 's/special/regular/g' '<>' \+;
But it doesn’t do a depth first traversal so it’s open to problems with parent directories haven’t been renamed first.
For those just wanting to rename directories you can use this command:
find /your/target/path/ -type d -execdir rename 's/special/regular/' '<>' \;
Note type is now d for directory, and using -execdir .
I haven’t been able to work out how to rename both files and directories in a single pass though.
Someone commented earlier that once it renamed the root folder then it couldn’t traverse the file tree any more. There is a -d switch available that does a depth traversal from the bottom-up, so the root would be renamed last I believe:
find -d /your/target/path/ -type d -execdir rename 's/special/regular/' '<>' \;
From the manpage ( man find ):
-d Cause find to perform a depth-first traversal, i.e., directories are visited in post-order and all entries in a directory will be acted on before the directory itself. By default, find visits directories in pre-order, i.e., before their contents. Note, the default is not a breadth-first traversal.
How to Rename a Directory in Linux
Renaming a directory is one of the most basic tasks you will perform on any operating system. The Linux terminal offers several different ways to rename directories using commands and scripts.
In this tutorial, we will go over the different methods you can use to rename a directory in Linux through the terminal window.
- A system running a Linux distribution
- An account with sudo privileges
- Access to the terminal window/command line
- Access to a text editor, such as Vim or Nano
Renaming Directories With the mv Command
The primary function of the mv command in Linux is moving files and directories from one place to another. It uses the following command syntax:
mv [options] [source] [destination]
Note: To learn more about using the mv command, check out our guide to moving directories in Linux.
If the destination directory does not exist, the mv command renames the source directory instead. In this case, the syntax changes to:
mv [options] [current directory name] [new directory name]
As an example, let’s say we have Directory1, Directory2, and Directory3 in our Home directory:
To rename Directory1 into Example_Directory with the mv command, use:
mv Directory1 Example_Directory
There is no output if the command is successful, so we need to use the ls command to verify the name change:
Renaming Directories With the rename Command
The rename command in Linux is a dedicated command used to change the names of files and directories. Using this command makes it easier to rename multiple directories at the same time.
Note: The rename command is not included in all Linux distributions by default. If your system is missing the rename command, install it with:
- For Ubuntu and Debian, use sudo apt install rename
- For CentOS and Fedora, use sudo yum install prename
- For Arch Linux, use sudo pacman -S rename
Renaming a Single Directory With the rename Command
The rename command uses the following syntax:
rename [options] 's/[expression]/[replacement]/' [file name]
The command renames the file by replacing the first occurrence of the expression with the replacement. For example, if we want to rename Directory1 to Example_Directory:
rename 's/Directory1/Example_Directory/' *
In this example, we can see that the rename command syntax consists of several sections:
- rename : Invokes the rename command.
- s : Short for substitute, indicates that we are replacing the expression with the replacement.
- / Directory1 : Specifies the expression or the part of the old directory name that you want to replace.
- /Example_Directory /: Defines the replacement or the new directory name.
- * : Searches the Home directory for names matching the provided expression.
Verifying the Home directory content with the ls command shows that the directory now has a new name:
Renaming Multiple Directories With the rename Command
The rename command provides a way to rename multiple directories at the same time without using bash scripts. For instance, if we want to rename Directory1, Directory2, and Directory3 to Folder1, Folder2, and Folder3:
rename -v 's/Directory/Folder/' *
- -v : Invokes the verbose output, listing each step of the process.
- ‘s/Directory/Folder/’ : Replaces Directory in the names of the search results with Folder.
- * : Searches the Home directory for names matching the provided expression.
The rename command can also translate file names by using the y argument instead of the s argument. In this case, it translates one string of characters into another, character-for-character.
The command above translates every a character into d, every b into e, and every c into f.
In the example below, we translated blank spaces in directory names to underscores (_).
Renaming Directories With the find Command
In case you are not sure where the directory you want to rename is located, using the find command with the mv command lets you search for it and rename it when it’s found:
find . -depth -type d -name [current directory name] -execdir mv <> [new directory name] \;
In the example above, -execdir executes the mv command once the find command locates the directory.
For instance, the command below finds and renames Directory1 into Example_Directory:
find . -depth -type d -name Directory1 -execdir mv <> Example_Directory \;
Renaming Directories With Bash Scripts
Using bash scripts is another way of renaming multiple directories at the same time. Unlike the rename command, bash scripts allow you to save a template for future use.
Start by creating the script with a text editor, such as Nano:
sudo nano rename_directories.sh
The following example is a bash script that searches for directories and appends the current date to their name:
#!/bin/bash #Searches for directories and renames them according to the specified pattern for d in * do if [ -d "$d" ] then mv -- "$d" "_$(date +%Y%m%d)" fi done
- The first line instructs the script to go through all files and directories in the current location.
- Lines 2 and 3 check for directories.
- Lines 4 and 5 append the current date to the name of any directory found.
Press Ctrl+X, type Y, and press Enter to close and save the script.
As an example, let’s use the script above to change the names of Directory1, Directory2, and Directory3, located in the Example directory.
Start by moving in to the Example directory:
Learn more about Linux cd command in our guide on how to change and move to different categories.
Next, execute the script by using the sh command:
Using the ls command allows us to verify the name change:
After reading this article, you should know how to rename directories in Linux using commands and bash scripts.
Learn more about using Linux commands in our Linux Commands All Users Should Know .