我需要删除所有扩展名为 .gif 的文件,只留下一个名称为“filename.gif”的文件。在终端中执行此操作的最佳方法是什么?
命令 rm*.gif
删除所有 gif 文件,包括文件filename.gif
。
答案1
以下是您可能应该使用的简单解决方案:
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
first, 放在其他表达式之前!你会发现我总是把它放在-delete
最后。如果你把它放在开头,它会被首先评估,然后全部该目录下的文件.
(包括不以 结尾的文件.gif
和位于 的深层子子子...目录中的文件.
)将被删除!
答案2
如果您使用的是bash
(默认 shell),extglob
shell 选项允许您使用扩展模式匹配语法。要启用它,请使用shopt
内置命令:
shopt -s extglob
(我将这一行包含在我的.bashrc
文件中。)
除其他事项外,它还授予对!()
运算符的访问权限,该运算符与括号内的任何模式匹配。对于您的目的:
rm !(filename).gif
更多信息请参阅man bash
“模式匹配”。
答案3
打开终端使用Ctrl++Alt并T输入:
find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;
-delete
和之间的区别在于,-exec rm -vf {} \;
使用第二个选项,您将能够看到哪些文件已被删除,因为有标志-v
。这是使用选项无法实现的-delete
。 (-name -delete
将打印文件名,但rm
使用-v
会显示每个文件是否被删除成功地已删除。
答案4
这是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
.
..