Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

If I have a group of files with a .htm extention, how can I rename them all to .html?

mv *.htm *.html

does not work.

share|improve this question
    
Just for the sake of completeness, ren *.htm *.html will work in Windows. –  Brian Burns Nov 8 at 22:27

8 Answers 8

up vote 42 down vote accepted

Or, you could use pure bash... (except for mv, that is..)

for file in *.htm; do mv "$file" "${file%.htm}.html"; done

and avoid the nasty basename stuff. ;)

Bash has an extensive set of variable expansion options. The one used here, '%', removes the smallest matching suffix from the value of the variable. The pattern is a glob pattern, so ${file%.*} would also work. The '%%' operator removes the largest matching suffix, and is interchangeable in the example above, as the pattern is fixed, ${file%%.*}.html would turn a.b.htm into a.html though.

See the variable substition section of the bash manpage for more neat tricks. There's a lot that can be done within bash directly.

share|improve this answer
1  
Also note that these parameter expansions are not limited to bash. They are available on all Bourne-derived shells (sh, ksh, bash, zsh, dash, ash, etc.). The expansions are a part of the POSIX specification for the “Shell Command Language” and are highly portable. –  Chris Johnsen May 11 '10 at 3:43
for file in *.htm; do
  mv $file `basename "$file" .htm`.html
done

Try it with an echo in front of the mv first time around.

The problem with your original is that "mv *.htm *.html" has the *s handled by the shell, so the mv command simply sees a list of all the .htm and .html files in the current directory. In other words, something like "mv foo.htm bar.htm stuff.htm six.htm file.htm". mv only knows how to handle more than 2 arguments if the last one is a directory.

share|improve this answer
1  
You should quote"$file", to handle spaces. –  Richard Hoskins Jul 19 '09 at 20:34
    
Your description of the original problem should be emphasised more strongly. This shell wildcard expansion behaviour is surprising and not intuitive for somebody coming from Windows land, and understanding what the shell does makes it clear why the original application of mv won't work. –  Greg Hewgill Jul 19 '09 at 21:57

rename(1) is a Perl utility that does exactly what you want. In this case:

rename 's/\.htm$/.html/' *htm

or if you are using sub directories as well

(requires Bash 4.0 and the globstar setting: shopt -s globstar)

rename 's/\.htm$/.html/' **/*htm

share|improve this answer
1  
rename is easier, but isn't a standard unix program; original question doesn't specify which unix. Seems to be "prename" in some places. –  freiheit Jul 19 '09 at 19:58
2  
rename comes with perl, and basically every unix comes with perl these days. –  TRS-80 Jul 19 '09 at 20:03
3  
yes, but not every unix includes ancillary programs like 'rename' when they put perl on the system. OSX, for instance, doesn't have "rename" on it. –  freiheit Jul 19 '09 at 21:47
1  
@William: The double asterisk syntax is only available in Bash 4 and up and only if it's turned on with shopt -s globstar (off by default). Also, Linux and Unix have directories rather than folders. –  Dennis Williamson Aug 11 '12 at 23:59
    
Thank you kindly for the corrections. –  William Bettridge-Radford Aug 12 '12 at 13:37

There shouldn't be spaces, newlines or other whitespace in the filenames, but this version of freiheit's answer handles those. It also uses $() instead of backticks for readability along with other benefits.

for file in *.htm
do
    mv "$file" "$(basename "$file" .htm).html"
done

Even better - for the special case of just adding on to the end:

for file in *.htm
do
    mv "$file" "${file}l"
done
share|improve this answer
    
+1 for the clever second solution. :) –  Sasha Chedygov Jun 21 '10 at 18:44

If you use Zsh you can use 'zmv'

share|improve this answer

The best tool is mmv.

mmv \*.htm #1.html

Other examples of use (and of other tools) in "GNU/Linux Command-Line Tools Summary".

share|improve this answer
1  
Your usage example fails. You need to escape #. –  Cristian Ciupitu Sep 12 '09 at 23:48
    
No, it works (I ALWAYS test before posting on SuperUser). The need to escape # depends on the shell you use (I use zsh). –  bortzmeyer Sep 13 '09 at 20:19

The util-linux-ng package (on Fedora) has a rename command similar to the one mentioned by TRS-80. You can use it like this:

rename .htm .html *.html
share|improve this answer

Yet another pure bash example using string replace.

for file in *.htm; do mv $file ${file/htm/html}; done

Extra - this replaces all the occurrences of a string

for file in *.htm; do mv $file ${file//htm/html}; done
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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