Find and replace string in a list of filenames

10,496

Solution 1

You can use find's exec option to (recursively) loop over all files, then use simple string replacements:

find . -type f -name "product-103*" \
-exec sh -c 'echo mv "$0" "${0/103/104}"' '{}' \;

Remove the echo when you're sure this does what you want.

Basically, what exec does is substitute the file name of every file found in {}, which is passed as an argument to sh -c. This argument is available as $0, thus the file name. We use this $0 argument in a mv call, where the second argument is the new file name. Here, 103 is replaced with 104. Note that double quotes are needed to correctly handle whitespace in the file names.

See String Manipulation in the Bash Scripting Guide.


With zsh's zmv (on OS X through /bin/zsh):

autoload -U zmv
zmv -Wn '*103*' '*104*'

Remove the -n option when this does what you need.

Solution 2

Perl is better for this.

find . -name 'product-103*' | perl -nle '($new=$_) =~ s/103/104/;rename $_,$new'

The following piece of code

perl -nle '($new=$_) =~ s/103/104/;rename $_,$new'

will eventually be expanded to

while (<>) {
    chomp;
    ($new=$_) =~ s/103/104/;
    rename $_, $new;
}

The <> operator will get each file name with an '\n' at the end and save it to $_, then chomp will chop the '\n' off. Then variable $new gets the old filename from $_ and replace 103 to 104. At last, rename just rename the file in question to its new name. For more details about the -n -l -e switch, refer to the perlrun part of perldoc.

Solution 3

for f in product-103*; do mv "$f" "${f/103/104}"; done
Share:
10,496

Related videos on Youtube

Dmt_K
Author by

Dmt_K

With nearly 14 years of experience in software development and eCommerce, I am utterly infatuated with technology. I eat challenge for breakfast, and like to make technological problems disappear. I am a strong team player, take constructive criticism extremely well. I have a strong belief, that to become better, we have to be around people that are more experienced than oneself. My favorite time spent at work is building and coding cutting edge interactive UI's that makes any system fun and easy to use, and is where my ability to think creatively and logically comes in very handy. My main life ingredient includes learning, and therefore enjoy constantly enriching my skills by taking online courses, watching endless hours of videos, and tinkering with whatever I can get my hands on. I enjoy doing carpentry, home DIY and tinkering with an Arduino and some electronics.

Updated on September 18, 2022

Comments

  • Dmt_K
    Dmt_K over 1 year

    I have a couple of files like so, (on Mac OS X):

    product-103-footer.tpl
    product-103-header.tpl
    product-103.tpl
    

    I want to replace '103' in all the filenames with something else using grep and sed, or something like that.

    How do I do it?

    Here's some pseudo command line of what I want to achieve

    find . /[103] | grep 103 | sed s/103/104/
    

    Hope this makes sense!

    EDIT:

    Getting closer:

    find . -name 'product-103*' -print | sed 's/103/104/g'
    
    • Dmt_K
      Dmt_K about 11 years
      I can replace a string using sed: echo 'product-103' | sed 's/103/104/g', but need to loop each file and rename them individually.