Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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


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!


Getting closer:

find . -name 'product-103*' -print | sed 's/103/104/g'
share|improve this question
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. – josef.van.niekerk Mar 26 '13 at 13:48
up vote 8 down vote accepted

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.

share|improve this answer

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 (<>) {
    ($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.

share|improve this answer
for f in product-103*; do mv "$f" "${f/103/104}"; done
share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .