从终端中删除具有特定扩展名的文件(除一个文件外)

从终端中删除具有特定扩展名的文件(除一个文件外)

我需要删除所有扩展名为 .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

只要确保你永远不要把-deletefirst, 放在其他表达式之前!你会发现我总是把它放在-delete最后。如果你把它放在开头,它会被首先评估,然后全部该目录下的文件.(包括不以 结尾的文件.gif和位于 的深层子子子...目录中的文件.)将被删除!

了解更多信息请参阅手册页bashsh这些示例中使用的命令如下:mvrm[,以及(尤其是)find

答案2

如果您使用的是bash(默认 shell),extglobshell 选项允许您使用扩展模式匹配语法。要启用它,请使用shopt内置命令:

shopt -s extglob

(我将这一行包含在我的.bashrc文件中。)

除其他事项外,它还授予对!()运算符的访问权限,该运算符与括号内的任何模式匹配。对于您的目的:

rm !(filename).gif

更多信息请参阅man bash“模式匹配”。

答案3

打开终端使用Ctrl++AltT输入:

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 *

由于已启用,所以将*匹配以 开头的文件名,但不会匹配或,因此您不会以这种方式影响父目录。.GLOBIGNOREdotglob...

相关内容