Rename files and directories recursively in ubuntu / bash

I want to rename all files and directories containing the word "special", "regular". It must maintain case sensitivity, so "Special" will not become "regular."

How can I do this in bash recursively?

+49
linux bash find ubuntu
Feb 21 '13 at 21:32
source share
6 answers

Try this ( bash --version > = 4 required):

 shopt -s globstar rename -n 's/special/regular/' ** 

Uncheck the -n switch when your tests are ok.

warning There are other tools with the same name that may or may not 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 

and not containing:

 ELF 

then this seems like the right tool =)

If not, to make it standard (usually already) in Debian and derived like Ubuntu :

 $ sudo update-alternatives --set rename /path/to/rename 

(replace /path/to/rename with the path of your perl rename command.




If you do not have this command, find the package manager to install it or run manually




Last but not least, this tool was originally written by Larry Wall, the father of Perl.

+65
Feb 21 '13 at 21:34
source share

Solution using find :

To rename files only:

 find /your/target/path/ -type f -exec rename 's/special/regular/' '{}' \; 

For directory renaming 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/' '{}' \+ 
+84
Feb 21
source share

If you don't mind installing another tool, you can use rnm :

 rnm -rs '/special/regular/g' -dp -1 * 

It will go through all directories / subdirectories (due to -dp -1 ) and replace the special ones with regular names.

+4
May 7 '16 at 9:33
source share

@speakr's answer was the key for me.

If you use -execdir to convert files and directories, you will also want to remove -type f from the example shown. To record this, use:

find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+

Also, consider adding the g (global) flag to the regular expression if you want to replace all occurrences of special with regular in the given file name, and not just the first occurrence. For example:

find /your/target/path/ -execdir rename 's/special/regular/g' '{}' \+

converts special-special.jpg to regular-regular.jpg . Without a global flag, you will get regular-special.jpg .

FYI: GNU Rename is not installed by default on Mac OSX. If you use the Homebrew package manager , brew install rename fix this.

+2
May 13 '17 at 17:08
source share

For those who just want to rename directories, you can use this command:

 find /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \; 

The entry type is now d for the directory and with -execdir .

I was not able to decide how to rename files and directories in one go.

Someone commented earlier that once he renamed the root folder, he would no longer be able to go through the file tree. There is an available -d switch that does a depth traversal from bottom to top, so the root will be renamed last, I believe:

 find -d /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \; 

From manpage ( man find ):

  -d Cause find to perform a depth-first traversal, ie, 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, ie, before their contents. Note, the default is not a breadth-first traversal. 
0
Feb 11 '17 at 4:31 on
source share

Here is another approach, which is more portable and independent of the rename command (since it may require different parameters depending on the distributions).

It recursively renames files and directories:

 find . -depth -name "*special*" | \ while IFS= read -r ent; do mv $ent ${ent%special*}regular${ent##*special}; done 

What does it do

  • use the find parameter with the -depth parameter to rearrange the results by crawling in depth (i.e., all entries in the directory appear before the directory itself).
  • do wildcards to modify only the last occurrence of a regular in the path.

Thus, the files are modified first, and then each parent directory.

example

We give the following tree:

 ├── aa-special-aa │ └── bb-special │ ├── special-cc │ ├── special-dd │ └── Special-ee └── special-00 

It generates these mv commands in a specific 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 get the following tree:

 ├── aa-regular-aa │ └── bb-regular │ ├── regular-cc │ ├── regular-dd │ └── Special-ee └── regular-00 
0
Dec 11 '18 at 23:54
source share



All Articles