Question

In a directory, I have a bunch of *.html files. I'd like to rename them all to *.txt

How can I do that? I use the bash shell.

Was it helpful?

Solution

For an better solution (with only bash functionality, as opposed to external calls), see one of the other answers.


The following would do and does not require the system to have the rename program (although you would most often have this on a system):

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

EDIT: As pointed out in the comments, this does not work for filenames with spaces in them without proper quoting (now added above). When working purely on your own files that you know do not have spaces in the filenames this will work but whenever you write something that may be reused at a later time, do not skip proper quoting.

OTHER TIPS

If using bash, there's no need for external commands like sed, basename, rename, expr, etc.

for file in *.html
do
  mv "$file" "${file%.html}.txt"
done
rename 's/\.html$/\.txt/' *.html

does exactly what you want.

This worked for me on OSX from .txt to .txt_bak

find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;

You want to use rename :

rename -S .html .txt *.html

This does exactly what you want - it will change the extension from .html to .txt for all files matching *.html.

Note: Greg Hewgill correctly points out this is not a bash builtin; and is a seperate Linux command. If you just need something on Linux this should work fine; if you need something more cross-platform then take a look at one of the other answers.

On a Mac...

  1. Install rename if you haven't: brew install rename
  2. rename -S .html .txt *.html

For Ubuntu Users :

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

Here is an example of the rename command:

rename -n ’s/\.htm$/\.html/’ *.htm

The -n means that it's a test run and will not actually change any files. It will show you a list of files that would be renamed if you removed the -n. In the case above, it will convert all files in the current directory from a file extension of .htm to .html.

If the output of the above test run looked ok then you could run the final version:

rename -v ’s/\.htm$/\.html/’ *.htm

The -v is optional, but it's a good idea to include it because it is the only record you will have of changes that were made by the rename command as shown in the sample output below:

$ rename -v 's/\.htm$/\.html/' *.htm
3.htm renamed as 3.html
4.htm renamed as 4.html
5.htm renamed as 5.html

The tricky part in the middle is a Perl substitution with regular expressions, highlighted below:

rename -v ’s/\.htm$/\.html/’ *.htm

After someone else's website crawl, I ended up with thousands of files missing the .html extension, across a wide tree of subdirectories.

To rename them all in one shot, except the files already having a .html extension (most of them had none at all), this worked for me:

cd wwwroot
find . -xtype f \! -iname *.html   -exec mv -iv "{}"  "{}.html"  \;  # batch rename files to append .html suffix IF MISSING

In the OP's case I might modify that slightly, to only rename *.txt files, like so:

find . -xtype f  -iname *.txt   -exec filename="{}"  mv -iv ${filename%.*}.{txt,html}  \; 

Broken down (hammertime!):

-iname *.txt
- Means consider ONLY files already ending in .txt

mv -iv "{}.{txt,html}" - When find passes a {} as the filename, ${filename%.*} extracts its basename without any extension to form the parameters to mv. bash takes the {txt,html} to rewrite it as two parameters so the final command runs as: mv -iv "filename.txt" "filename.html"

Fix needed though: dealing with spaces in filenames

This question explicitly mentions Bash, but if you happen to have ZSH available it is pretty simple:

zmv '(*).*' '$1.txt'

If you get zsh: command not found: zmv then simply run:

autoload -U zmv

And then try again.

Thanks to this original article for the tip about zmv.

This is the slickest solution I've found that works on OSX and Linux, and it works nicely with git too!

find . -name "*.js" -exec bash -c 'mv "$1" "${1%.js}".tsx' - '{}' \;

and with git:

find . -name "*.js" -exec bash -c 'git mv "$1" "${1%.js}".tsx' - '{}' \;

The command mmv seems to do this task very efficiently on a huge number of files (tens of thousands in a second). For example, to rename all .xml files to .html files, use this:

mmv ";*.xml" "#1#2.html"

the ; will match the path, the * will match the filename, and these are referred to as #1 and #2 in the replacement name.

Answers based on exec or pipes were either too slow or failed on a very large number of files.

Try this

rename .html .txt *.html 

usage:

rename [find] [replace_with] [criteria]

A bit late to the party. You could do it with xargs:

ls *.html | xargs -I {} sh -c 'mv $1 `basename $1 .html`.txt' - {}

Or if all your files are in some folder

ls folder/*.html | xargs -I {} sh -c 'mv $1 folder/`basename $1 .html`.txt' - {}

If you prefer PERL, there is a short PERL script (orignally written by Larry Wall, the creator of PERL) that will do exactly what you want here: tips.webdesign10.com/files/rename.pl.txt. For your example the following should do the trick

rename.pl 's/html/txt/' *.html

= )

(Thanks @loretoparisi for the updated URL)

Unfortunately it's not trivial to do portably. You probably need a bit of expr magic.

for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done

Remove the echo once you're happy it does what you want.

Edit: basename is probably a little more readable for this particular case, although expr is more flexible in general.

This is a good way to modify multiple extensions at once:

for fname in *.{mp4,avi}
do
   mv -v "$fname" "${fname%.???}.mkv"
done

Note: be careful at the extension size to be the same (the ???)

Nice & simple!

find . -iname *.html  -exec mv {} "$(basename {} .html).text"  \;

Here is what i used to rename .edge files to .blade.php

for file in *.edge; do     mv "$file" "$(basename "$file" .edge).blade.php"; done

Works like charm.

One line, no loops: ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}

cbongiorno@ip-172-31-26-242:~/pgsql$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.json  ac8453e2-0d82-4d43-b80e-205edb754700.json
cbongiorno@ip-172-31-26-242:~/pgsql$ ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
cbongiorno@ip-172-31-26-242:~/pgsql$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.txt  ac8453e2-0d82-4d43-b80e-205edb754700.txt
cbongiorno@ip-172-31-26-242:~/pgsql$ 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top