如何在使用“find”时排除点下划线 ._ 文件?

如何在使用“find”时排除点下划线 ._ 文件?

我正在使用这个命令:

ls -R |find . -name "*.avi*" -or -name "*.mp4*" -or -name "*.mkv*" > movies.txt

问题是电影被列出两次!例如:

./_NEW/Rogue (2020)/Rogue.2020.1080p.BluRay.x264.AAC5.1-[YTS.MX].mp4
./_NEW/Rogue (2020)/._Rogue.2020.1080p.BluRay.x264.AAC5.1-[YTS.MX].mp4

我怎样才能消除多余的线?(./_NEW/Rogue (2020)/._Rogue.2020.1080p.BluRay.x264.AAC5.1-[YTS.MX].mp4

我已经尝试使用find和尝试了许多命令grep,但它们总是被列出两次!

答案1

您的问题存在不准确之处在你的回答中。

  1. 在您的原始命令 ( ls -R | find … > movies.txt)中ls,它只是一个负担,因为find它忽略了其标准输入。到达 的任何内容movies.txt都完全来自find,而不依赖于ls

  2. 您写道“电影列出了两次”。电影不是。名称以 开头的文件._不是电影。它们是与实际电影相关的元数据,一种在无法严格将元数据存储为元数据的文件系统中存储某些元数据的临时方法。它们是。我没有使用过 Mac,但如果某些 macOS 专用软件在要求显示隐藏文件时将它们隐藏起来,我也不会感到惊讶。您可能从未注意到它们,它们是设计用来供您的操作系统查看的,而不是供您查看。但它们只是假肢,任何不知道其用途的软件都会将它们视为常规文件(毕竟它们是常规文件)。您find确实找到了它们。

  3. 您通过将管道连接到 解决了该问题grep -v "._"。这不是一个严格的解决方案,因为grep解释._为正则表达式,其中.表示任何字符。该模式._匹配__行首之外的任何字符;但您的find .生成的行必须以 (literal) 开头.,因此_(如果有)出现任何地方在文件的相对路径中,将使你grep -v过滤掉此路径。任何地方,不一定是在文件本身的基本名称中;可能是在某个目录的名称中。

    可以通过转义模式中的点 ( \._) 或通过指定grep按字面意思处理模式 ( grep -F) 来解决此问题。如果我是你,我也会确保._直接出现在 之后/。命令如下

    find … | grep -vF '/._'
    

    (在这种特殊情况下不需要引号,但我认为始终引用模式是一个好习惯grep,即使 shell 在未引用时不会对它们执行任何操作;因为这样在 shell 可以干扰的情况下就不会忘记引用。)

    注意,这将过滤掉名称以 开头的整个目录._。可能您的系统中没有这样的目录;或者至少这样的目录中没有电影。

    带有换行符(如果有)的路径可能会产生误导grep。这是一个普遍的问题,我不会详细说明。很可能您不会在路径中使用换行符(但从技术上讲您可以)。

关于不准确性,说得够多了。这就是我要做的。我会排除名称以._usingfind开头的文件:

find . -type f ! -name '._*' '(' -name '*.avi' -o -name '*.mp4' -o -name '*.mkv' ')'

笔记:

  • -or不是一个 POSIX 选项,-o是。

  • 括号需要

  • 如果您的find支持-iname(不区分大小写的类似物-name),那么您可能想要使用它。或者-name '*.[Mm][Pp]4'等等。

  • 除了通过扩展名识别文件(这更像是 Windows 概念)之外,还可以实现自定义测试以find通过内容进行识别。在 Ubuntu 中,这将是这样的:

    find . -type f -exec sh -c '
       for f do
          file --brief --mime-type "$f" | grep -q "^video/" && printf "%s\n" "$f"
       done
     ' sh {} +
    
    • 我不知道filemacOS 是否支持--mime-type
    • 该命令会为每个常规文件生成一个file、一个grep和(平均)一些小数部分sh。它很慢。
    • 该命令不会打印._文件路径,因为这些文件不是视频。添加! -name '._*'会加快速度,所以无论如何这都是一个好主意。
    • 第二个sh解释如下:中的第二个 sh 是什么sh -c 'some shell code' sh

我认为苹果选择了._ 字首隐藏相关文件,这要归功于前导点。我个人认为他们应该添加一些后缀(即末尾的字符串)。这将允许您使用-name '*.avi'和类似的测试而无需找到这些文件(但不是-name '*.avi*')。例如备份文件以~基本名称结尾在此背景下是很好的。

答案2

啊!我找到了答案,尽管我不认为这是最优雅的命令:

find . -name "*.avi*" -or -name "*.mp4" -or -name "*.mkv*" |grep -v "._"

相关内容