195

Dead simple.

How do I rename

05_h.png
06_h.png

to

05_half.png
06_half.png

At least, I think it's simple, but it's hard to Google for this kind of thing unless you already know.

Thanks....

Richard
  • 31,629
  • 29
  • 108
  • 145

12 Answers12

391

Just use bash, no need to call external commands.

for file in *_h.png
do
  mv "$file" "${file/_h.png/_half.png}"
done

Do not add #!/bin/sh

For those that need that one-liner:

for file in *.png; do mv "$file" "${file/_h.png/_half.png}"; done
sclarson
  • 4,362
  • 3
  • 32
  • 44
bash-o-logist
  • 6,665
  • 1
  • 17
  • 14
  • 8
    Nice use of bash's built-in string replacement rather than sed – dandrews Aug 05 '12 at 18:48
  • 4
    is file/_h.png/_half.png regex? – user2799603 Feb 27 '14 at 14:56
  • 19
    No, the format is this: ${string/substring/substitution} – "substitute first occurrence". For more info check this cheat sheet (section "strings"): http://bruxy.regnet.cz/linux/bash_cheatsheet/bash_cheatsheet.pdf – WindRider Apr 25 '14 at 09:08
  • Thank you. I was able to make minimal changes and use it to remove "@1x.png" from lots of files at once. Here's that: for file in *.png; do mv "$file" "${file/@1x.png/.png}"; done – Gazzini Feb 18 '15 at 05:04
  • 13
    Any reasons for `Do not add #!/bin/sh` ? I tried both working with/ without this statement. – Ryan Oct 26 '15 at 14:21
  • @Ryan It's really a comment so it doesn't matters if you use it or not. So, Maybe he said that because it is useless to type that line here. – Ishan Jain Aug 27 '17 at 11:01
  • 7
    @Ryan @Ishan Jain In fact it indicates the backend shell that must execute the script. sh and bash are different shells so it may affect the script behavior and syntax. Since the script uses a bash built-in string replacement you should add the header `#!/bin/bash`. This said, bash is normally the default shell in many computers so you won't find many differences :D You can find more information [here](https://askubuntu.com/questions/141928/what-is-difference-between-bin-sh-and-bin-bash) – Cristian Ramon-Cortes Nov 22 '17 at 07:37
81

Try rename command:

rename 's/_h.png/_half.png/' *.png

Update:

example usage:

create some content

$ mkdir /tmp/foo
$ cd /tmp/foo
$ touch one_h.png two_h.png three_h.png
$ ls 
one_h.png  three_h.png  two_h.png

test solution:

$ rename 's/_h.png/_half.png/' *.png
$ ls
one_half.png  three_half.png  two_half.png
Michał Šrajer
  • 30,364
  • 7
  • 62
  • 85
  • @CarolineAlexiou: what was the problem? command not found? Did something else than rename? Please be more specific so we can help. – Michał Šrajer Apr 10 '14 at 08:38
  • 1
    @CarolineAlexiou: I added example test session. Please try it. You probably have some typo. What is the output of `ls` ? what is the `rename ...` you try? – Michał Šrajer Apr 10 '14 at 09:27
  • I tested it with a dummy example and it worked. I am pretty sure I didnt have a typo though. Will write back if I find what was the problem. Thanks. – grasshopper Apr 10 '14 at 09:38
  • 4
    Doesn't work in bash on Mac, fwiw. `rename` is not a standard Unix tool. – tandrewnichols Jun 09 '15 at 18:07
  • 2
    @tandrewnichols, try out [homebrew](http://brew.sh/) - once installed, rename becomes available in seconds with `brew install rename` – Simbamangu Jun 28 '15 at 14:16
  • Understood. I already have homebrew. Just pointing that it's non-standard, so it won't work by default in every bash environment. – tandrewnichols Jun 28 '15 at 19:15
  • just to clearify, the right syntax is rename 'search_word' 'replace_word' *.png – moveax Aug 19 '15 at 14:32
  • 5
    as for me rename didn't work with `'s//'` - I referenced man and there was simple synopsis: `rename [options] expression replacement file...`, on CentOS 7 , version: `rename from util-linux 2.23.2` – tymik Oct 20 '15 at 08:58
  • 2
    keep in mind that `.` matches ANY character, not just a dot – for literal dot, use `\.` instead – Meisner Dec 11 '16 at 11:00
  • This solution enables using multiple vars if double quoting substitution pattern, the marked one don't. i.e. `rename "s/${VAR1}_h.png/${VAR2}_half.png/" *.png` – danius Apr 28 '19 at 09:37
  • awesome command - basically it works like `sed` but instead of a text file filenames are used as input – Petr Javorik Nov 23 '19 at 09:05
15
for f in *.png; do
  fnew=`echo $f | sed 's/_h.png/_half.png/'`
  mv $f $fnew
done

Or in one-liner:

for f in *.png; do mv "$f" "$(echo $f | sed 's/_h.png$/_half.png/g')"; done
Top-Master
  • 7,611
  • 5
  • 39
  • 71
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • 1
    This is great for doing a dry run beforehand. I first replaced `mv $f $fnew` with `echo $fnew` as the second line to make sure the output looks sane. – lobati Apr 28 '17 at 04:07
14

Are you looking for a pure bash solution? There are many approaches, but here's one.

for file in *_h.png ; do mv "$file" "${file%%_h.png}_half.png" ; done

This presumes that the only files in the current directory that end in _h.png are the ones you want to rename.

Much more specifically

for file in 0{5..6}_h.png ; do mv "$file" "${file/_h./_half.}" ; done

Presuming those two examples are your only. files.

For the general case, file renaming in has been covered before.

sorpigal
  • 25,504
  • 8
  • 57
  • 75
7

Use the rename utility written in perl. Might be that it is not available by default though...

$ touch 0{5..6}_h.png

$ ls
05_h.png  06_h.png

$ rename 's/h/half/' *.png

$ ls
05_half.png  06_half.png
Fredrik Pihl
  • 44,604
  • 7
  • 83
  • 130
5

I had a similar question: In the manual, it describes rename as

rename [option] expression replacement file

so you can use it in this way

rename _h _half *.png

In the code: '_h' is the expression that you are looking for. '_half' is the pattern that you want to replace with. '*.png' is the range of files that you are looking for your possible target files.

Hope this can help c:

James Yen
  • 51
  • 1
  • 3
5
for i in *_h.png ; do
  mv $i `echo "$i"|awk -F'.' '{print $1"alf."$2}'`
done
ztank1013
  • 6,939
  • 2
  • 22
  • 20
2

Another approach can be manually using batch rename option

Right click on the file -> File Custom Commands -> Batch Rename and you can replace h. with half.

This will work for linux based gui using WinSCP etc

Easwar
  • 21
  • 1
2

One liner:
for file in *.php ; do mv "$file" "_$file" ; done

Jadeye
  • 3,551
  • 4
  • 47
  • 63
2

Although the answer set is complete, I need to add another missing one.

for i in *_h.png;
  do name=`echo "$i" | cut -d'_' -f1`
  echo "Executing of name $name" 
  mv "$i" "${name}_half.png"
done
Tharindu Sathischandra
  • 1,654
  • 1
  • 15
  • 37
2

I had to rename the prefix of files and I found this answer with a solution like this:

for i in h_*; do mv ${i/#h_/half_}; done

If pattern begins with #, it must match at the beginning of the expanded value of parameter. If pattern begins with %, it must match at the end of the expanded value of parameter.

from man bash

lucrp
  • 582
  • 9
  • 11
2

Use the rename utility:

rc@bvm3:/tmp/foo $ touch 05_h.png 06_h.png
rc@bvm3:/tmp/foo $ rename 's/_h/_half/' * 
rc@bvm3:/tmp/foo $ ls -l
total 0
-rw-r--r-- 1 rc rc 0 2011-09-17 00:15 05_half.png
-rw-r--r-- 1 rc rc 0 2011-09-17 00:15 06_half.png
C. Ramseyer
  • 2,322
  • 2
  • 18
  • 22