我有一个充满.bak文件和一些其他文件的文件夹。我需要删除该文件夹中所有.bak文件的扩展名。如何创建一个接受文件夹名称的命令,然后删除该文件夹中所有.bak文件的扩展名?如何删除文件的扩展名?
谢谢。
我有一个充满.bak文件和一些其他文件的文件夹。我需要删除该文件夹中所有.bak文件的扩展名。如何创建一个接受文件夹名称的命令,然后删除该文件夹中所有.bak文件的扩展名?如何删除文件的扩展名?
谢谢。
要从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是替代解决方案。
有几种方法可以删除文件后缀:
在bash和Kornshell,您可以使用环境变量过滤。在BASH manpage中搜索${parameter%word}
以获取完整信息。基本上,#
是左侧过滤器和%
是右侧过滤器。您可以记住这一点,因为#
位于%
的左侧。
如果您使用的是双滤光片(即##
或%%
,你想上最重要的比赛进行筛选。如果你有一个单一的过滤器(即#
或%
,你想上最小的匹配过滤器。
匹配什么是过滤出来,你得到的字符串的其余部分:
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
命令查找指定的文件。 -print0
用NUL符号分隔文件的名称 - 这是文件名中不允许的几个字符之一。 -d $
\ means that your input separators are NUL symbols. See how nicely the
find -print0 and
读-d $'\ 0'`在一起?
你应该几乎从不使用for file in $(*.bak)
方法。如果文件名称中有空格,这将失败。
请注意,该命令实际上并不移动任何文件。相反,它会生成一个带有所有文件重命名列表的find.out
文件。当你执行大量文件的命令时,你应该总是这样做,以确保一切正常。
一旦你已经确定,在find.out
所有的命令都是正确的,你可以像一个shell脚本运行:
$ bash find.out
+1用于解释,特别是'find.out'技术。在对文件系统做一些可能很丑陋的事情之前,这是一个非常好的方法来进行理智检查。 –
rename .bak '' *.bak
(rename
是在util-linux
包)
您可以随时使用find命令获取所有子目录
for FILENAME in `find . -name "*.bak"`; do mv --force "$FILENAME" "${FILENAME%.bak}"; done
如果文件名中有空格,该怎么办? –
谢谢。这很好。我可以让这个命令为任何目录执行任务吗?我不想一直光盘进入目录。 – bashboy
btw,完成的含义是什么? – bashboy