This question already has an answer here:

In a directory there are these files and more:

  • file1.txt
  • file1.html
  • file1.pdf
  • ...

Every file1 should be replaced with newfile:

  • newfile.txt
  • newfile.html
  • newfile.pdf
  • ...

I've tried:

for f in $(ls file1*); do mv $f newfile*; done

this does replace all files with file1 to one file newfile*.

for f in $(ls file1*); do mv $f ${f/$f/"newfile"}; done

this also replaces all files with file1 to one file newfile. Or

find . -name "file1.*" -exec sh -c 'mv I DONT KNOW' _ {} \;

I don't understand how to set a part of the file name as a variable and replace this.

What is the simplest way to do this with mv?

marked as duplicate by Wildcard, Archemar, GAD3R, Toby Speight, thrig Mar 8 '17 at 15:15

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.



for f in ./file1.*; do
  echo mv "$f" "newfile.${f##*.}"

The code only displays what the mv commands will be. When this is what you want, remove the echo in front of the mv command.


If you are running on Linux, then the easiest way to achieve it is to use rename (which is part of the util-linux package:

rename 'file1' 'newfile' file1*

This will do what you described. The rename expects three arguments:

  1. what to look for in the filename
  2. what to use as a replacement
  3. a file mask to work on

I quickly searched on rename and this was the first hit with examples: http://linux.icydog.net/rename.php

UPDATE If you don't have rename on your system, but do have bash, then you can do a batch rename as follows (this is an equivalent of rename given above):

for f in file1*; do mv -v "$f" "${f/file1/newfile}"; done

Use expr to get the last part of each name. I am assuming here that you know the prefix is "file1" otherwise you might need another loop.

for f in $(ls file1.*)
suffix=`expr $f : '.*\.\(.*\)'`
mv -v file1.${suffix} newfile.${suffix}

Note that to do this properly, you might want to check that the destination doesn't already exist, or you could use the "-n" flag on mv to avoid clobbering an existing file.


With GNU find:

find . -maxdepth 1 -name "file1*" -printf "%f\0" | xargs -0 -I {} echo mv -v {} new{}

If everything looks okay, remove echo.


On Debian-based systems, the rename utility is Perl rename and has a slightly different syntax:

rename 's/file1/newfile/' file1*

The first argument is a Perl expression that will be applied to each file name found.


With the help of @cuonglm's answer, I found out what was missing:

find . -name "file1.*" -exec sh -c 'mv "$1" "newfile.${1##*.}"' _ {} \;

Not the answer you're looking for? Browse other questions tagged or ask your own question.