Find and replace filename recursively in a directory

find . -name "123*.txt" -exec rename 's/^123_//' {} ";" 

will do it. No AWK, no for, no xargs needed, but rename, a very useful command from the Perl lib. It is not always included with Linux, but is easy to install from the repos.


In case you want to replace string in file name called foo to bar you can use this in linux ubuntu, change file type for your needs

find -name "*foo*.filetype" -exec rename 's/foo/bar/' {} ";"

you could check 'rename' tool

for example

rename 's/^123_//' *.txt

or (gawk is needed)

find . -name '123_*.txt'|awk '{print "mv "$0" "gensub(/\/123_(.*\.txt)$/,"/\\1","g");}'|sh

test:

kent$  tree
.
|-- 123_a.txt
|-- 123_b.txt
|-- 123_c.txt
|-- 123_d.txt
|-- 123_e.txt
`-- u
    |-- 123_a.txt
    |-- 123_b.txt
    |-- 123_c.txt
    |-- 123_d.txt
    `-- 123_e.txt

1 directory, 10 files

kent$  find . -name '123_*.txt'|awk '{print "mv "$0" "gensub(/\/123_(.*\.txt)$/,"/\\1","g");}'|sh

kent$  tree
.
|-- a.txt
|-- b.txt
|-- c.txt
|-- d.txt
|-- e.txt
`-- u
    |-- a.txt
    |-- b.txt
    |-- c.txt
    |-- d.txt
    `-- e.txt

1 directory, 10 files

You can do it this way:

find . -name '123_*.txt' -type f -exec sh -c '
for f; do
    mv "$f" "${f%/*}/${f##*/123_}"
done' sh {} +

No pipes, no reads, no chance of breaking on malformed filenames, no non-standard tools or features.

Tags:

Bash