在 Linux 上,如何区分目录,按名称排除文件,但包括同名的目录?

在 Linux 上,如何区分目录,按名称排除文件,但包括同名的目录?

考虑以下目录/文件结构(所有叶节点都是常规文件,但这并不重要):

$ tree
.
├── cool_1
│   ├── dumb
│   │   ├── file1
│   │   └── file2
│   └── foo
│       └── dumb
└── cool_2
    ├── dumb
    │   ├── file1
    │   └── file2
    └── foo
        └── dumb

我想对两个目录进行递归比较,但不包括常规文件 <root>/foo/dumb但不是全部目录 <root>/dumb

我查看了--exclude--exclude-from如果man 1 diff有办法创建一个模式来实现这一点,我感到很困惑,除了编写一个手动执行递归的脚本或类似的东西。我如何比较目录并排除我想要的和仅排除我想要的?

答案1

我假设您想要diff -r cool_1 cool_2排除。

--exclude并且--exclude-from确实太有限

有一种方法,虽然有点麻烦,但其核心却非常简单:

  1. 将您想要的两个目录复制diff到其他地方。例如,让目标目录为target/。然后我们的基本命令是cp -R cool_1 cool_2 target/

    笔记:

    • target/不希望预先包含cool_1cool_2。一个好主意是创建一个新的空目录 ( mkdir target),然后cp进入该目录。

    • 您想要-P(将符号链接复制为符号链接)。

    • cool_1理想情况下,和中的整个目录层次结构cool_2都属于单个文件系统。如果是这样,请选择同一文件系统内的目标目录,然后:

      • 使用cp -l并创建到常规文件的硬链接,而不是实际复制它们(尽管您cp可能支持也可能不支持-l);
      • cp --reflink=always或者,如果文件系统支持 reflinks 并且您的cp支持,则使用创建 reflinks --reflink。如果没有充分的理由使用 reflinks,则应使用硬链接。使用 reflinks 的充分理由是,当cool_1或下面的某些常规文件cool_2是不可变的,并且您无法为其创建新的硬链接时。

      这样,您将避免不必要的实际复制。这不仅与 I/O 有关,硬链接或重新链接消耗的额外磁盘空间也比实际复制少得多。

    该命令如下:

     cp -RPl cool_1 cool_2 target/
    
  2. 进入目标目录:

    cd target/
    

    确保没有错误并且您位于目标目录中。

  3. 用任何手段来真正消除您想要排除的文件。使用rm、 或 中手动删除它们mc,或使用一些自动化方法。例如此命令:

    find cool_1 cool_2 -name dumb ! -type d -delete
    

    将删除目录类型文件之外的所有文件cool_1cool_2以基本名称命名的文件。不可移植,如有必要,请使用;参见dumb-delete-exec rm {} \;这个问题。如果目标目录(现在是我们的.)仅包含cool_1cool_2那么您可以简化并对整个目录采取行动:find . …

    你可能会发现这个问题很有用:递归搜索具有排除和包含的文件

    用于tree检查层次结构是否良好。您还可以运行类似diff -r cool_1 ../cool_1diff -r cool_2 ../cool_2查看已删除的内容。如果删除的内容过多,请记住,您可以随时从原始目录再次复制(硬链接、重新链接)。

    由于您甚至可以逐个删除(或重新添加)文件,因此可以实现任意排除。

  4. diff -r在目标目录内使用:

    diff -r cool_1 cool_2
    

    这里cool_1/cool_2/包含您想要排除的文件,因此无需告知diff排除任何内容。

  5. 最终删除目标目录:

    cd .. && rm -r target/
    

相关内容