6

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.

5

Try:

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

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.

5

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
1

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.*)
do
suffix=`expr $f : '.*\.\(.*\)'`
mv -v file1.${suffix} newfile.${suffix}
done

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.

1

With GNU find:

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

If everything looks okay, remove echo.

1

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.

0

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.