我有一个文件夹,里面装满了.bak文件和其他一些文件。我需要删除该文件夹中所有.bak文件的扩展名。如何创建一个接受文件夹名称的命令,然后删除该文件夹中所有.bak文件的扩展名?
感谢。
答案 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