'Rename multiple files, but only rename part of the filename in Bash
I know how I can rename files and such, but I'm having trouble with this.
I only need to rename test-this
in a for loop.
test-this.ext
test-this.volume001+02.ext
test-this.volume002+04.ext
test-this.volume003+08.ext
test-this.volume004+16.ext
test-this.volume005+32.ext
test-this.volume006+64.ext
test-this.volume007+78.ext
Solution 1:[1]
If you have all of these files in one folder and you're on Linux you can use:
rename 's/test-this/REPLACESTRING/g' *
The result will be:
REPLACESTRING.ext
REPLACESTRING.volume001+02.ext
REPLACESTRING.volume002+04.ext
...
rename
can take a command as the first argument. The command here consists of four parts:
s
: flag to substitute a string with another string,test-this
: the string you want to replace,REPLACESTRING
: the string you want to replace the search string with, andg
: a flag indicating that all matches of the search string shall be replaced, i.e. if the filename istest-this-abc-test-this.ext
the result will beREPLACESTRING-abc-REPLACESTRING.ext
.
Refer to man sed
for a detailed description of the flags.
Solution 2:[2]
Use rename
as shown below:
rename test-this foo test-this*
This will replace test-this
with foo
in the file names.
If you don't have rename
use a for
loop as shown below:
for i in test-this*
do
mv "$i" "${i/test-this/foo}"
done
Solution 3:[3]
Function
I'm on OSX and my bash doesn't come with rename
as a built-in function. I create a function in my .bash_profile
that takes the first argument, which is a pattern in the file that should only match once, and doesn't care what comes after it, and replaces with the text of argument 2.
rename() {
for i in $1*
do
mv "$i" "${i/$1/$2}"
done
}
Input Files
test-this.ext
test-this.volume001+02.ext
test-this.volume002+04.ext
test-this.volume003+08.ext
test-this.volume004+16.ext
test-this.volume005+32.ext
test-this.volume006+64.ext
test-this.volume007+78.ext
Command
rename test-this hello-there
Output
hello-there.ext
hello-there.volume001+02.ext
hello-there.volume002+04.ext
hello-there.volume003+08.ext
hello-there.volume004+16.ext
hello-there.volume005+32.ext
hello-there.volume006+64.ext
hello-there.volume007+78.ext
Solution 4:[4]
Without using rename
:
find -name test-this\*.ext | sed 'p;s/test-this/replace-that/' | xargs -d '\n' -n 2 mv
The way it works is as follows:
find
will, well, find all files matching your criteria. If you pass-name
a glob expression, don't forget to escape the*
.Pipe the newline-separated* list of filenames into
sed
, which will:a. Print (
p
) one line.b. Substitute (
s//
)test-this
withreplace-that
and print the result.c. Move on to the next line.
Pipe the newline-separated list of alternating old and new filenames to
xargs
, which will:a. Treat newlines as delimiters (
-d '\n'
).b. Call
mv
repeatedly with up to 2 (-n 2
) arguments each time.
For a dry run, try the following:
find -name test-this\*.ext | sed 'p;s/test-this/replace-that/' | xargs -d '\n' -n 2 echo mv
*: Keep in mind it won't work if your filenames include newlines.
Solution 5:[5]
to rename index.htm to index.html
rename [what you want to rename] [what you want it to be] [match on these files]
rename .htm .HTML *.htm
renames index.htm to index.html It will do this for all files that match *.htm in the folder.
Solution 6:[6]
thx for your passion and answers. I also find a solution for me to rename multiple files on my linux terminal and directly add a little counter. With this I have a very good chance to have better SEO names.
Here is the command
count=1 ; zmv '(*).jpg' 'new-seo-name--$((count++)).jpg'
I also do a live coding video and publush it to YouTube
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | dogbane |
Solution 3 | Deepak Mahakale |
Solution 4 | user16785526 |
Solution 5 | Shanavas M |
Solution 6 | Rogoit |