删除目录中扩展名为pdf的文件以外的所有文件

我有一个包含以下内容的目录:

x.pdf y.zip z.mp3 a.pdf 

我想删除除x.pdfa.pdf之外的所有文件。 我如何从终端这样做? 没有子目录,因此不需要任何递归。

 cd  find . -type f ! -iname "*.pdf" -delete 
  • 第一个命令将带您进入要删除文件的目录
  • 第二个命令将删除除文件名中以.pdf结尾的所有文件

例如,如果您的主文件夹中有一个名为temp的目录:

 cd ~/temp 

然后删除文件:

 find . -type f ! -iname "*.pdf" -delete 

这将删除除xyz.pdf之外的所有文件。

您可以将这两个命令组合到:

 find ~/temp -type f ! -iname "*.pdf" -delete 

. 是当前目录。 ! 意味着除最后的.pdf之外的所有文件。 -type f只选择文件,而不选择目录。 -delete表示删除它。

注意:此命令将删除当前目录以及所有子目录中的所有文件(pdf文件除外,但包括隐藏文件)。 ! 必须在-name之前来。 简单地, -name将仅包含.pdf ,而-iname将包括.pdf.PDF

要仅在当前目录中删除而不在子目录中删除,请添加-maxdepth 1

 find . -maxdepth 1 -type f ! -iname "*.pdf" -delete 

使用bash的扩展shell globbing,你可以删除任何扩展名为.pdf以外的文件

 rm -- *.!(pdf) 

如@pts所述, --字符表示任何命令选项的结束,在极少数名称以-字符开头的文件中使命令安全。

如果你想删除没有任何扩展名的文件以及那些扩展名不是.pdf ,那么正如@DennisWilliamson所指出的,你可以使用

 rm -- !(*.pdf) 

默认情况下应启用扩展通配符,但如果不启用,则可以使用

 shopt -s extglob 

特别是如果你打算在脚本中使用它,重要的是要注意如果表达式与任何东西都不匹配(即如果目录中没有非pdf文件),那么默认情况下,glob将被未扩展地传递给rm命令,导致错误

 rm: cannot remove `*.!(pdf)': No such file or directory 

您可以使用nullglob shell选项修改此默认行为,但这有其自身的问题。 有关更全面的讨论,请参阅NullGlob – Greg的Wiki

删除到垃圾箱 :

 $ cd  $ gvfs-trash !(*.pdf) 

或者通过mv命令(但是这样你就无法从垃圾桶恢复它,因为它没有记录.trashinfo信息,所以这意味着你将文件移动到了一个目的地 ,如下所示)。

 mv !(*.pdf) ~/.local/share/Trash/files 

最简单的方法:在某处创建另一个目录(如果你只是在一个目录中删除,而不是递归,它甚至可以是一个子目录); 将所有.pdf移到那里; 删除其他一切; 将pdf移回; 删除中间目录。

快速,简单,您可以准确地看到您正在做的事情。 只需确保中间目录与您正在清理的目录位于同一设备上,以便移动重命名,而不是复制!

使用bash的GLOBIGNORE:

 GLOBIGNORE=x.pdf:a.pdf rm * unset GLOBIGNORE 

从bash的手册页:

 GLOBIGNORE:

            以冒号分隔的模式列表,用于定义集合
            路径名扩展忽略的文件名。

快速测试:

 mkdir /tmp/foooooo cd /tmp/foooooo touch x.pdf y.zip z.mp3 a.pdf GLOBIGNORE=x.pdf:a.pdf ls -1 * 

输出:

 y.zip
 z.mp3

小心并撰写:使用xargs

这是我喜欢的方法,因为它让我非常小心:构建一种方法来显示我想要删除的文件,然后使用xargs将它们发送到rm 。 例如:

  • 我告诉我一切
  • ls | grep pdf ls | grep pdf向我展示了我想要保留的文件。 嗯。
  • ls | grep -v pdf ls | grep -v pdf显示了相反的结果: 除了我想要保留的内容之外的所有内容。 换句话说,它显示了我想要删除的内容列表。 在做任何危险之前我都可以确认一下。
  • ls | grep -v pdf | xargs rm ls | grep -v pdf | xargs rm将该列表准确发送给rm进行删除

正如我所说,我主要是因为它提供的安全性:对我来说不是偶然的。 另外两个优点:

  • 它可以组合; 您可以根据需要使用lsfind来获取初始列表。 你可以在缩小列表的过程中使用你喜欢的任何其他东西 – 另一个grep ,一些awk或者其他什么。 如果您只需要删除名称中包含颜色的文件,则可以采用相同的方式构建它。
  • 您可以将每个工具用于其主要目的。 我更喜欢使用find for findrm for removal,而不是必须记住find接受-delete标志。 如果你再次这样做,你可以组成替代解决方案; 也许不是rm ,你可以创建一个trash命令,将文件移动到垃圾箱(允许“取消删除”)并管道到而不是rm 。 你不需要find支持该选项,你只需要管道。

更新

请参阅@pabouk的注释,了解如何修改它以处理某些边缘情况,例如文件名中的换行符, my_pdfs.zip等文件名等。

我通常从交互式Python解释器中解决这些问题:

 mic@mic ~ $ python >>> import os >>> for f in os.listdir('.'): ... if not f.endswith('.pdf'): ... os.remove(f) 

它可能比使用findxargs更长,但它非常有弹性,我确切地知道它的作用,而不必先研究它。

通过使用强大的file命令,这个问题的答案(与我之前的答案相比)更好。

 $ file -i abc.pdf abc: application/pdf; charset=binary 

现在你的问题:

 cd  for var in ./* do if file -i "$var" | grep -q 'application/pdf\;' then echo "$var" fi done 

for命令的作用是以变量$var的forms给出当前目录中的文件。 if-then命令通过从file -i "$var" | grep -q 'application/pdf\;'取出退出状态0来输出pdf文件的名称 file -i "$var" | grep -q 'application/pdf\;' 命令,只有找到pdf文件才会使退出状态为0

 rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}') 

警告! 最好先试试

 ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}') 
 rm -i -- !(*@(a|x).pdf) 

读取为,删除所有不是a.pdfx.pdf

这通过使用2个扩展的globs来工作,外部的!()来否定包含的glob,它本身要求glob必须在.pdf后缀之前匹配一个或多个ax模式。 请参阅glob#extglob 。

 $ ls -a .dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3 $ echo -- !(a.pdf) -- x.pdf y.zip z.mp3 $ echo -- !(x.pdf) -- a.pdf y.zip z.mp3 $ echo -- !(a.pdf|x.pdf) -- y.zip z.mp3 $ echo -- !(@(a|x).pdf) # NOTE.that this matches the .dotfiles* as well -- . .. .dotfile1 .dotfile2 y.zip z.mp3 $ echo -- !(*@(a|x).pdf) # but this doesn't -- y.zip z.mp3 $ echo rm -i -- !(*@(a|x).pdf) rm -i -- y.zip z.mp3 

便携式shell方式

 $ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done' 

几乎POSIX并兼容任何Bourne风格的shell( kshbashdash )。 非常适合便携式脚本,当你不能使用bash的扩展shell globbing时。

perl的:

 $ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d' 

或稍微清洁:

 $ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d' 

另类python

 python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'