Mass Rename Files with bash

3

1

I've got a bunch of numbered files like this:

file #01.ext
file #02.ext
file #03.ext
file #04.ext
file #05.ext

And what I want is to make them all have three digits (two leading 0's) instead of one, so;

file #001.ext
file #002.ext
file #003.ext
file #004.ext
file #005.ext

My thought is to use sed to replace the # with #0 (which in my case is good enough, there are no files over #99 yet). All the files are in the same folder, how would I do that?

Rob

Posted 2011-10-30T00:37:22.483

Reputation: 2 152

Answers

2

To protect files with 3 digits already

for f in "file #"*.ext; do
  num=${f#file #}
  num=${num%.ext}
  new=$(printf "file #%03d.ext" $num)
  echo mv "$f" "$new"
done

This will display in the console the commands to execute, but not actually rename the files.

Once you are happy with what it intends to do, you can make it rename the files by removing the word echo and re-running it.

glenn jackman

Posted 2011-10-30T00:37:22.483

Reputation: 18 546

This could've saved me a step earlier. I've been doing it all with sed, and used ls | grep '[0-9]\{3\}' | sed 's|\(.*\)#0\(.*\)|mv "&" "\1#\2"|' | sh just to make them have two digits, and then did it the way I listed above. – Rob – 2011-10-30T15:20:09.560

I've changed this to the answer, now that I'm learning more about all of this, this is more practical and adaptable. – Rob – 2011-11-08T18:44:34.593

One can use the -v option to printf: printf -v new "file #%03d.ext" $num – glenn jackman – 2012-11-01T22:19:09.463

2

You don't need sed for this. It can be done with a very simple command:

rename 's/#0/#00/' *.ext

Example:

temp$ ls
file #01.ext  file #02.ext  file #03.ext  file #04.ext  file #05.ext
temp$ rename 's/#0/#00/' *.ext
temp$ ls
file #001.ext  file #002.ext  file #003.ext  file #004.ext  file #005.ext

Nick Brunt

Posted 2011-10-30T00:37:22.483

Reputation: 672

I don't have perl rename installed. – Rob – 2012-11-02T22:32:35.117

I lied, I used to not have it installed but I do on this archlinux install. – Rob – 2012-11-02T22:39:33.817

1

This does the trick from within the folder:

ls | sed 's/\(.*\)#\(.*\)/mv "&" "\1#0\2"/' | sh

Rob

Posted 2011-10-30T00:37:22.483

Reputation: 2 152

ls piped to sed piped to sh? My brain is melting. – phogg – 2011-11-04T13:14:07.720

The you probably don't want to see find piped through grep piped through sed piped to sh. :D – Rob – 2011-11-04T13:48:53.707

Any particular reason this is bad? – Rob – 2011-11-04T14:50:15.050

In fact, I'd be much better with find -> generate shell code. The reason for this is that find is less likely to mangle filenames than ls. In the real world I'd just use mmv for this, or a while read command substitution loop pulling nul-terminated filenames from find. Or, if the files are nicely globbable, a simple for loop as glenn used in his answer. – phogg – 2011-11-04T17:42:22.440

0

This is a hybrid solution:

ls | sed -r "s/(.*#)([0-9]+)([^0-9]*)/printf 'mv -v \"&\" \"%s%03d%s\"' \"\1\" \"\2\" \"\3\"/e;e"

potong

Posted 2011-10-30T00:37:22.483

Reputation: 1