7

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?

0

6 Answers 6

8

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 
4

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.

3

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.

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

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

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