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?

cuonglm
  • 153,898

6 Answers6

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
galaxy
  • 859
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.

Walter A
  • 736
cuonglm
  • 153,898
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.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
terdon
  • 242,166
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.

GregD
  • 226
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.

Cyrus
  • 12,309
1

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

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