Recursively change file extensions in Bash

RegexLinuxBashShellSh

Regex Problem Overview


I want to recursively iterate through a directory and change the extension of all files of a certain extension, say .t1 to .t2. What is the bash command for doing this?

Regex Solutions


Solution 1 - Regex

Use:

find . -name "*.t1" -exec bash -c 'mv "$1" "${1%.t1}".t2' - '{}' +

If you have rename available then use one of these:

find . -name '*.t1' -exec rename .t1 .t2 {} +
find . -name "*.t1" -exec rename 's/\.t1$/.t2/' '{}' +

Solution 2 - Regex

None of the above solutions worked for me on a fresh install of debian 14. This should work on any Posix/MacOS

find ./ -depth -name "*.t1" -exec sh -c 'mv "$1" "${1%.t1}.t2"' _ {} \;

All credits to: https://askubuntu.com/questions/35922/how-do-i-change-extension-of-multiple-files-recursively-from-the-command-line

Solution 3 - Regex

If your version of bash supports the globstar option (version 4 or later):

shopt -s globstar
for f in **/*.t1; do
    mv "$f" "${f%.t1}.t2"
done 

Solution 4 - Regex

I would do this way in bash :

for i in $(ls *.t1); 
do
    mv "$i" "${i%.t1}.t2" 
done

EDIT : my mistake : it's not recursive, here is my way for recursive changing filename :

for i in $(find `pwd` -name "*.t1"); 
do 
    mv "$i" "${i%.t1}.t2"
done

Solution 5 - Regex

Or you can simply install the mmv command and do:

mmv '*.t1' '#1.t2'

Here #1 is the first glob part i.e. the * in *.t1 .

Or in pure bash stuff, a simple way would be:

for f in *.t1; do
    mv "$f" "${f%.t1}.t2"
done

(i.e.: for can list files without the help of an external command such as ls or find)

HTH

Solution 6 - Regex

My lazy copy-pasting of one of these solutions didn't work, but I already had fd-find installed, so I used that:

fd --extension t1 --exec mv {} {.}.t2

From fd's manpage, when executing a command (using --exec):

          The following placeholders are substituted by a
          path derived from the current search result:

          {}     path
          {/}    basename
          {//}   parent directory
          {.}    path without file extension
          {/.}   basename without file extension

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAmal AntonyView Question on Stackoverflow
Solution 1 - RegexanubhavaView Answer on Stackoverflow
Solution 2 - RegexPaul Oskar MayerView Answer on Stackoverflow
Solution 3 - RegexchepnerView Answer on Stackoverflow
Solution 4 - RegexjrjcView Answer on Stackoverflow
Solution 5 - RegexzmoView Answer on Stackoverflow
Solution 6 - RegexRichard TurnerView Answer on Stackoverflow