如何删除文件的扩展名?

时间:2013-07-24 20:08:23

标签: linux bash unix cygwin

我有一个文件夹,里面装满了.bak文件和其他一些文件。我需要删除该文件夹中所有.bak文件的扩展名。如何创建一个接受文件夹名称的命令,然后删除该文件夹中所有.bak文件的扩展名?

感谢。

5 个答案:

答案 0 :(得分:8)

要从BASH变量的末尾删除字符串,请使用${var%ending}语法。这是a number of string manipulations available to you in BASH之一。

像这样使用:

# Run in the same directory as the files
for FILENAME in *.bak; do mv "$FILENAME" "${FILENAME%.bak}"; done

这可以很好地作为一个单行,但你也可以将其包装为一个脚本,以在任意目录中工作:

# If we're passed a parameter, cd into that directory. Otherwise, do nothing.
if [ -n "$1" ]; then
  cd "$1"
fi
for FILENAME in *.bak; do mv "$FILENAME" "${FILENAME%.bak}"; done

请注意,虽然引用变量几乎总是一个好习惯,但如果您的任何文件名可能包含空格,for FILENAME in *.bak仍然很危险。阅读 David W。的答案以获得更强大的解决方案,并this document寻找替代解决方案。

答案 1 :(得分:6)

有多种方法可以删除文件后缀:

在BASH和Kornshell中,您可以使用环境变量过滤。在BASH manpage中搜索${parameter%word}以获取完整信息。基本上,#左侧过滤器%右侧过滤器。您可以记住这一点,因为#位于%的左侧。

如果您使用双重过滤器(即##%%,则尝试过滤最大匹配。如果您有一个过滤器(即#或{{1你试图过滤最小的匹配。

匹配的是过滤,你得到了其余的字符串:

%

请注意,这是 glob 匹配,而不是正则表达式匹配!如果要删除文件后缀:

file="this/is/my/file/name.txt"
echo ${file#*/}   #Matches is "this/` and will print out "is/my/file/name.txt"
echo ${file##*/}  #Matches "this/is/my/file/" and will print out "name.txt"
echo ${file%/*}   #Matches "/name.txt" and will print out "/this/is/my/file"
echo ${file%%/*}  #Matches "/is/my/file/name.txt" and will print out "this"

file_sans_ext=${file%.*} 将匹配期间及其后的所有字符。由于它是单个.*,因此它将匹配字符串右侧的最小 glob 。如果过滤器无法匹配任何内容,则与原始字符串相同。

您可以使用以下内容验证文件后缀:

%

或者你可以这样做:

if [ "${file}" != "${file%.bak}" ]
then
    echo "$file is a type '.bak' file"
else
    echo "$file is not a type '.bak' file"
fi

请注意,这将删除文件扩展名的句点。

接下来,我们将循环:

file_suffix=$(file##*.}
echo "My file is a file '.$file_suffix'"

find . -name "*.bak" -print0 | while read -d $'\0' file do echo "mv '$file' '${file%.bak}'" done | tee find.out 命令查找您指定的文件。 find使用NUL符号分隔文件的名称 - 这是文件名中不允许的少数几个字符之一。 -print0 \ 0 -d $找-print0 means that your input separators are NUL symbols. See how nicely the一起阅读-d $'\ 0'`?

您几乎不应该使用and方法。如果文件名称中有空格,则会失败。

请注意,此命令实际上并未移动任何文件。相反,它会生成一个for file in $(*.bak)文件,其中包含所有文件重命名的列表。当您执行操作大量文件的命令时,您应该总是这样做,以确保一切正常。

一旦确定find.out中的所有命令都正确,就可以像shell脚本一样运行它:

find.out

答案 2 :(得分:1)

警告:没有错误检查:

#!/bin/bash
cd "$1"
for i in *.bak ; do mv -f "$i" "${i%%.bak}" ; done

答案 3 :(得分:1)

rename .bak '' *.bak

rename位于util-linux包中)

答案 4 :(得分:0)

您始终可以使用find命令获取所有子目录

for FILENAME in `find . -name "*.bak"`; do mv --force "$FILENAME" "${FILENAME%.bak}"; done