如何列出目录中具有指定扩展名的文件以外的所有文件?


28

假设我有一个包含.txt.pdf和其他文件的文件夹。我想列出“其他”文件(即不具有扩展名.txt.pdf的文件)。您对此有什么建议吗?

我知道如何列出没有给定扩展名的文件。例如,如果我要列出除.txt文件之外的所有文件,则可以

find -not -iname "*.txt"

要么

ls | grep -v '\.txt$' | column

似乎有效。但是,如何列出除.txt文件 .pdf文件之外的所有内容?看来我需要在findor中使用某种逻辑“或” grep


2
请记住,对于隐藏的点文件,lsvs findvs globlob 的行为可能有所不同。
jw013'9

1
要记住的另一件事:find将遍历子目录,就像递归一样ls。使用-maxdepth 1with find使它的行为更像ls
2012年

因此,无需递归,只需在当前目录中列出文件?
雏菊2012年

Answers:


28

假设其中有的适当版本ls,这可能是最简单的方法:

ls -I "*.txt" -I "*.pdf"

如果要遍历所有子目录:

ls -I "*.txt" -I "*.pdf" -R

8
GNU ls选项不是可移植的。
bahamat 2012年

4
ls无论如何,它并不是真正属于可移植脚本,因此我一直假设OP仅询问交互式使用。
jw013 2012年

1
为什么ls不便携?那我该怎么用呢?
Freedo

28

寻找支持 -o

find . ! '(' -name '*.txt' -o -name '*.pdf' ')'

您需要括号以赋予优先权。Find做很多事情;我建议通读其联机帮助页。

您也可以执行或的操作grep(但实际上,您不应解析的输出ls

ls | grep -Ev '\.(txt|pdf)$' | column

1
谢谢!为什么我不应该解析输出ls
安德鲁(Andrew)

6
@Andrew首先,因为它很脆弱(考虑一个带有换行符的文件名-是的,那是一个有效的文件名-找到-print0 / -exec / -delete / etc。可以避免该问题);第二,因为通常有一种更简单的方法。
derobert 2012年

除了find联机帮助页,我还全力推荐有关的Unix Power Tools文章find,例如docstore.mik.ua/orelly/unix3/upt/ch09_06.htmdocstore.mik.ua/orelly/unix3/upt/ch09_12.htm
通配符

只是为了帮助解释对人类的陈述:find . NOT ( *.txt OR *.pdf )
Wisbucky

12

使用bash扩展的glob(使用开启shopt -s extglob),glob !(*.txt|*.pdf)应该起作用。您可以将此glob直接传递给任何带有文件参数的命令,包括但不限于ls


1
+1,但是如果您有子目录,那么它们的内容也会列出;使用-d以避免:ls -d !(*.txt|*.pdf)
legends2k 2014年

谢谢,我正是在寻找可以接受多个文件的语法,这很适合在这里stackoverflow.com/questions/216995/…–
Freedo

6

zshextendedglob

print -rl -- *~*.(txt|pdf)

要么

print -rl -- ^*.(txt|pdf)

kshglob(是,是ksh glob而不是“ bash Extended globbing”):

print -rl -- !(*.txt|*.pdf)

请记住,尽管这些也排除了点文件。

ksh93具有FIGNORE(错误)功能:

FIGNORE='@(.|..|*.txt|*.pdf)'
printf '%s\n' *


3

正如derobert所建议的,最好的选择是使用find。但是,实际上您可以将结果与其他命令一起用于管道中。

GNU(和某些BSD的)find支持-print0谓词,该谓词告诉它打印以NUL字符结尾的文件名,文件名中不允许使用该字符,并保证不会发生冲突。可以指示其他命令将NUL用作其输入定界符。

其中最重要的是GNU xargs,它将运行您指定的命令,并将文件列表作为命令行参数传递给它。您想xargs -r0与find一起运行-print0例如:

find . -type f ! \( -name \*.pdf -o -name \*.txt \) -print0 | xargs -r0 ls -ld

这样可以安全地打印所有PDFtxt文件的长目录,包括名称中带有空格或不可打印字符的文件。

您还可以将其与GNU一起使用tar,如下所示:

tar -zcf myarchive.tar.gz --null --files-from <(
  find . -type f ! -name \*.tar.gz -print0)

这将建立一个名称不以.tar.gz结尾的所有文件的tar.gz文件

rsync还接受带有-0参数的以空分隔的文件,其他几个也一样。但是xargs通常是用于这种目的的胶水。或find-exec功能。


tar命令示例是一个很好的例子。但是,对于大多数目的来说,它-exec是一个更好的选择。
2015年

1

如果没有子目录

ls !(*.pdf|*.txt)

应该也可以!

ls -I "*.pdf" -I "*.txt"

是常见的方式。


0

作为补充,如果您使用与bash兼容的shell,则可以使用GLOBIGNORE变量从模式匹配中排除结果。从男人那里:

   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.

在您的特定情况下:

sh$ (GLOBIGNORE='*.pdf:*.txt'; ls -d *)

请注意,我将该命令作为子外壳程序运行(使用括号),以便不更改交互式外壳程序的GLOBIGNORE环境变量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.