Terminal: Remove specific extension recursively I have a folder, containing many other folders.

Some of the folders contained therein (at arbitrary depths) have a specific extension, let's say, .ext:

TopFolder
+ Folder1
| + Folder11.ext
|   +Folder111
+ Folder2.ext


I want to use Terminal to remove that extension from all folders in any subfolder so that it looks like this:

TopFolder
+ Folder1
| + Folder11
|   +Folder111
+ Folder2


I've played around with find and xargs, but I couldn't get it to work.
Try this:

$ find TopFolder -print
Topfolder
Topfolder/Folder1
Topfolder/Folder1/Folder11.ext
Topfolder/Folder1/Folder11.ext/Folder111
Topfolder/Folder2.ext
$ find TopFolder -name '*.ext' -print | while read i; do mv -v "$i" "${i%.ext}";done
$ find TopFolder
TopFolder
TopFolder/Folder1
TopFolder/Folder1/Folder11
TopFolder/Folder1/Folder11/Folder111
TopFolder/Folder2


The first and last find are just to show the before and after hierarchy. Here's how the middle find, the one that does the actual work, works:

$ find TopFolder -name '*.ext' -print


This finds everything in TopFolder matching the pattern '*.ext', that is all files and directories ending in .ext, and prints the path to each. If you want to limit it to just directories, add -type d.

while read i; do


read i reads from standard input into the shell variable i. while loops until read i returns false, which it does on end-of-file. Being find's output is being piped to the while, read's standard input is the output of the find, so read will read a line at a time from the find output until there's none left.

mv -v "$i" "${i%.ext}"


This does the actual rename. The -v is in there just so you can see what's happening, you can leave it out if you want. "$i" is the source, quoted in case any element of the path in $i contains spaces. "${i%.ext}" is the destination, which is $i, with any trailing .ext removed.

done


This just terminates the while loop.

Note that this is in bash, it should be doable in other fairly modern shells, but the syntax may be a bit different.