Answers:
这是您可能应该使用的简单解决方案:
mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif
.keep
扩展名没有什么特别的,它只是使扩展名暂时不以.gif
。结尾。
如果您一定不能重命名文件(并且在脚本情况下这很重要):
for X in *.gif; do
if [ "$X" != "filename.gif" ]; then
rm "$X"
fi
done
或者,您可以像这样简短地写:
for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done
您可能更喜欢使用find
;它的功能非常强大,你可能会认为这是更具可读性,它更好把手与像怪异字符的文件名*
在其中。
find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete
我已经使用-not
运算符来提高可读性,但是如果POSIX合规性很重要-如果您未使用GNU find,或者如果该脚本用于您打算重新分发给其他人或在各种系统上运行的脚本-您应该使用!
运算符:
find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete
一件方便的事find
是,您可以轻松地修改该命令以区分大小写,以便它也可以查找和删除具有以下扩展名的文件.GIF
:
find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete
请注意,我已经用-iname
代替-name
了搜索模式,*.gif
但没有将它用于filename.gif
。大概您知道文件的确切名称,并且-iname
不仅在扩展名中,而且在文件名中的任何地方都将匹配备用大小写。
所有这些解决方案仅删除当前目录中立即存在的文件。它们不会删除当前目录中未包含的文件,也不会删除当前目录的子目录中的文件。
如果要删除当前目录中所有位置的文件(即,包括子目录和这些子目录的子目录中的文件,等等,即当前目录或其任何后代中包含的文件),请使用find
不带 maxdepth -1
:
find . -not -name 'filename.gif' -name '*.gif' -delete
注意这一点!
您也可以使用设置其他值-maxdepth
。例如,要删除当前目录及其子孙目录中的文件,但不能更深:
find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete
只要确保您从未把-delete
其他表达式放在首位即可!您会看到我总是放在-delete
最后。如果您将其放在开头,则将首先对其进行评估,然后将删除其下的所有文件.
(包括未结尾的.gif
文件和的深层sub-sub ... subdirect目录中的文件.
)!
find
。
find
与*
for循环相比,如何更好地处理其中包含的奇怪文件名?for循环可以*
很好地处理文件,因为您已经使用了双引号。
如果您使用的是bash
(默认外壳程序),则extglob
shell选项允许您使用扩展模式匹配语法。要启用它,请使用shopt
内置命令:
shopt -s extglob
(我在.bashrc
文件中包括了这一行。)
除其他事项外,它授予!()
操作员访问权限,该操作员匹配不在括号内的任何模式。为了您的目的:
rm !(filename).gif
更多信息可在man bash
“模式匹配”下找到。
extglob
必须启用的增加的复杂性,但是如果禁用它,则不会发生任何不好的情况(在这种情况下,这是行不通的)。即使我没有shopt -s extglob
任何(或全局)配置文件,它似乎也是默认启用的。如果有一个简单的解释说明为什么它对我有用,那么您可能需要将其添加到此答案中。或者我可以发布一个新问题。
有GLOBIGNORE
变量。来自man bash
:
GLOBIGNORE
A colon-separated list of patterns defining the set of filenames
to be ignored by pathname expansion. If a filename matched by a
pathname expansion pattern also matches one of the patterns in
GLOBIGNORE, it is removed from the list of matches.
因此,一种简单的方法是将其设置GLOBGINORE
为相关文件名:
$ touch {a,b,c,d}.png
$ echo *.png
a.png b.png c.png d.png
$ GLOBIGNORE=c.png
$ echo *.png
a.png b.png d.png
因此,在您的情况下:
GLOBIGNORE=filename.gif; rm *.gif
当然,由于GLOBIGNORE
包含模式,因此您可以在要排除模式时使用它:
$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png
(?!)的优点的GLOBIGNORE
是,设置自动排除.
,并..
从被匹配,并且它能够dotglob
:
The GLOBIGNORE shell variable may be used to restrict the set of file‐
names matching a pattern. If GLOBIGNORE is set, each matching filename
that also matches one of the patterns in GLOBIGNORE is removed from the
list of matches. The filenames ``.'' and ``..'' are always ignored
when GLOBIGNORE is set and not null. However, setting GLOBIGNORE to a
non-null value has the effect of enabling the dotglob shell option, so
all other filenames beginning with a ``.'' will match. To get the old
behavior of ignoring filenames beginning with a ``.'', make ``.*'' one
of the patterns in GLOBIGNORE. The dotglob option is disabled when
GLOBIGNORE is unset.
因此,一种删除目录中所有文件和文件夹的简单方法:
GLOBIGNORE=.; rm -r *
该*
会与开始相匹配的文件名.
,因为GLOBIGNORE
启用dotglob
,但它不会匹配.
或者..
,这样就不会影响这样的父目录。