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?
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?
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 executableand not containing:
ELFthen 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.
** (stands for recursive) maybe already enabled.
 
 – Gilles Quenot
 Feb 21 '13 at 21:41
 
 
 
 -n switch ? It works very well. Do you have bash4 ? bash --version
 
 – Gilles Quenot
 Feb 21 '13 at 22:00
 A solution using find:
To rename files only:
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/' '{}' \+-exec command ; in the find manpage.
 
 – speakr
 Feb 27 '15 at 14:09
 find … -execdir … '{}' + instead of … '{}' \;. Clarification added.
 
 – speakr
 Jan 16 '17 at 10:20
 
 
 
 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.
@speakr's answer was the clue for me.
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.
/special/regular/regular-specilal.jpeg
 
 – inetphantom
 Mar 8 '19 at 9:40
 
 
 
 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.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 ${ent%special*}regular${ent##*special}; doneWhat it does
-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).That way the files are modified first and then each parent directory.
Example
Giving the following tree:
├── aa-special-aa
│   └── bb-special
│       ├── special-cc
│       ├── special-dd
│       └── Special-ee
└── special-00It 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-00To obtain the following tree:
├── aa-regular-aa
│   └── bb-regular
│       ├── regular-cc
│       ├── regular-dd
│       └── Special-ee
└── regular-00For rename version rename from util-linux 2.23.2 the following command worked for me:
find . -type f -exec rename mariadb mariadb-proxy '{}' \;