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\".
@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.
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/' '{}' \+
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:
Files:
find /path/ -type f -iregex '.*special.*' -execdir rename 's/special/regular/g' '{}' \+;
Directories:
find /path/ -type d -iregex '.*special.*' -execdir rename 's/special/regular/g' '{}' \+;
Files and Directories
find /path/ -iregex '.*special.*' -execdir rename 's/special/regular/g' '{}' \+;
For rename
version rename from util-linux 2.23.2
the following command worked for me:
find . -type f -exec rename mariadb mariadb-proxy '{}' \;
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.
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.