I have many files with .txt extension. How to remove .txt extension for multiple files in linux?
I found that
rename .old .new *.old
substitutes .old
extension to the .new
Also I want to do this for files in sub-folders.
I have many files with .txt extension. How to remove .txt extension for multiple files in linux?
I found that
rename .old .new *.old
substitutes .old
extension to the .new
Also I want to do this for files in sub-folders.
rename
is slightly dangerous, since according to its manual page:
rename will rename the specified files by replacing the first occurrence of...
It will happily do the wrong thing with filenames like c.txt.parser.y
.
Here's a solution using find
and bash
:
find -type f -name '*.txt' | while read f; do mv "$f" "${f%.txt}"; done
Keep in mind that this will break if a filename contains a newline (rare, but not impossible).
If you have GNU find, this is a more solid solution:
find -type f -name '*.txt' -print0 | while read -d $'\0' f; do mv "$f" "${f%.txt}"; done
I use this:
find ./ -name "*.old" -exec sh -c 'mv $0 `basename "$0" .old`.new' '{}' \;
The Perl version of rename can remove an extension as follows:
rename 's/\.txt$//' *.txt
This could be combined with find in order to also do sub-folders.
You can explicitly pass in an empty string as an argument.
rename .old '' *.old
And with subfolders, find . -type d -exec rename .old '' {}/*.old \;
. {}
is the substitute for the entry found with find
, and \;
terminates the arglist for the command given after -exec
.
In case it helps, here's how I do it with zsh:
for f in ./**/*.old; do
mv "${f}" "${f%.old}"
done
The ${x%pattern}
construct in zsh removes the shortest occurence of pattern
at the end of $x
. Here it is abstracted as a function:
function chgext () {
local srcext=".old"
local dstext=""
local dir="."
[[ "$#" -ge 1 ]] && srcext="$1"
[[ "$#" -gt 2 ]] && dstext="$2" dir="$3" || dir="${2:-.}"
local bname=''
for f in "${dir}"/**/*"${srcext}"; do
bname="${f%${srcext}}"
echo "${bname}{${srcext} → ${dstext}}"
mv "${f}" "${bname}${dstext}"
done
}
Usage:
chgext
chgext src
chgext src dir
chgext src dst dir
Where `src` is the extension to find (default: ".old")
`dst` is the extension to replace with (default: "")
`dir` is the directory to act on (default: ".")
For subfolders:
for i in `find myfolder -type d`; do
rename .old .new $i/*.old
done
In Fish, you can do
for file in *.old
touch (basename "$file" .old).new
end