I want to know which command I can use to rename files like this.

Let's say, for instance, the old filenames are:

...so on...

What I am expecting is to extract them with the format like {filename}_predict-{times}-{rounds}.png, then I can replace it into another pattern, for example, {filename}.png-result-{times}.png.

So, the aforementioned filenames will be changed to match the pattern:

...so on...

Does anyone has the Linux command/tool to do thing like this? I don't wanna write the Python script to complete this.


I have just found out that there is a tool that can easily manipulate filenames in GNU/Linux which is mmv. It is quite much easier than the posted answers.

In my case,

mmv "*_predict-*-*.png" "#1.png-result-#2.png"

It tries to substitute each part with a wildcard pattern, consequently, we can re-use the part with #1, #2, and so on.


With the help of rename command you can edit it, I am assuming that all files are in same directory and you want to rename all .png files.:

find -name \*.png -exec sh -c 'x=$( rename -v 's/_predict/.png-result/g' $0 ) ;  rename  's/-500//g' "${x##*\./}" ;' {} \;

Run this command in that directory where files are.

So basically it runs two times rename command first one to remove _predict and second one to remove -500.

Here I used x=$( rename -v 's/_predict/.png-result/g' $0 ) because after first change in the file name, I stored this new name in variable x and then used this value for second modification.

Command rename 's/-500//g' "${x##*\./}" ; is used because value of x is like ./0_predict-1-500.png renamed as ./0.png-result-1-500.png so I just want 0.png-result-1-500.png and ${x##*\./} will do that.


Try also

$ for FN in *.png; do IFS="_-." read F P T R X <<< "$FN"; echo mv "$FN" "$F.$X-result-$T.$X"; done
mv 0_predict-1-500.png 0.png-result-1.png
mv 0_predict-2-500.png 0.png-result-2.png
mv 0_predict-3-500.png 0.png-result-3.png
mv 1_predict-1-500.png 1.png-result-1.png
mv 1_predict-2-500.png 1.png-result-2.png
mv 1_predict-3-500.png 1.png-result-3.png
mv 2_predict-1-500.png 2.png-result-1.png

and remove the echo if happy with the result. We're looping through the target files, read the file name components using an adapted IFS variable and a "here string", and then reassemble the components to form the desired final file name for the mv command.


To add yet another variation, this uses the bash shell's =~ pattern matching operator in the [[ test command to pick out the elements to be rearranged:

for f in ./*_predict-*-*.png
  [[ $f =~ ^\./([[:digit:]]+)_predict-([[:digit:]]+)-([[:digit:]]+).png ]]
  echo mv -- "$f" "${BASH_REMATCH[1]}.png-result-${BASH_REMATCH[2]}.png"

Remove the echo if the results look correct.


Mention all the files in a file which needs to be renamed

awk  '{print "mv -v" " " $1 " " substr($1,1,1)".png-result-"substr($1,11,1)".png"}' filename |sh

I have mentioned -v for verbose mode

This is how it shows output for renaming

awk  '{print "mv -v" " " $1 " " substr($1,1,1)".png-result-"substr($1,11,1)".png"}' filename|sh

`0_predict-1-500.png' -> `0.png-result-1.png'
`0_predict-2-500.png' -> `0.png-result-2.png'
`0_predict-3-500.png' -> `0.png-result-3.png'
`1_predict-1-500.png' -> `1.png-result-1.png'
`1_predict-2-500.png' -> `1.png-result-2.png'
`1_predict-3-500.png' -> `1.png-result-3.png'
`2_predict-1-500.png' -> `2.png-result-1.png'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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