如何复制目录结构但只包含某些文件

Cha*_*han 3 bash shell ubuntu

我在 Windows 中找到了我的问题的解决方案,但我使用的是 Ubuntu:如何复制目录结构但仅包含使用 Windows 批处理文件的某些文件?

正如标题所说,如何递归复制目录结构但只包含一些文件?例如,给定以下目录结构:

folder1
  folder2
    folder3
      data.zip
      info.txt
      abc.xyz
    folder4
    folder5
      data.zip
      somefile.exe
      someotherfile.dll
Run Code Online (Sandbox Code Playgroud)

文件data.zipinfo.txt可以出现在目录结构中的任何地方。如何复制完整的目录结构,但只包含名为data.zipand 的info.txt文件(应忽略​​所有其他文件)?

生成的目录结构应如下所示:

copy_of_folder1
  folder2
    folder3
      data.zip
      info.txt
    folder4
    folder5
      data.zip
Run Code Online (Sandbox Code Playgroud)

你能告诉我一个 Ubuntu 的解决方案吗?

use*_*158 5

我没有漂亮的衬里,但由于没有其他人回答,你可以随时:

find . -name 'file_name.extension' -print | cpio -pavd /path/to/receiving/folder
Run Code Online (Sandbox Code Playgroud)

对于复制目录后的每个特定文件。

(当然,请确保您首先位于原始文件夹中!:))

  • @ayniam:“手动复制所有内容”是什么意思?使用“cpio”的全部目的是让机器进行复制。 (2认同)

Rog*_*ahl 5

$ rsync --recursive --include="data.zip" --include="*.txt" --filter="-! */" dir_1 copy_of_dir_1
Run Code Online (Sandbox Code Playgroud)

排除dir3它在树中的任何位置(即使它包含与--includes匹配的文件):

--exclude 'dir3/' (before `--filter`)
Run Code Online (Sandbox Code Playgroud)

dir3仅在树中的特定位置排除,请指定从源目录开始的绝对路径:

--exclude '/dir1/dir2/dir3/' (before `--filter`)
Run Code Online (Sandbox Code Playgroud)

dir3仅当它在时排除dir2,但无论在何处dir2

--exclude 'dir2/dir3/' (before `--filter`)
Run Code Online (Sandbox Code Playgroud)

通配符也可用于路径元素,其中*表示具有任何名称的目录,**表示多个嵌套目录。

要仅指定要包含的文件和目录,请运行两个rsyncs,一个用于文件,另一个用于目录。在单个文件中完成的问题rsync在于,当您不包含目录时,rsync将不会输入目录,因此不会发现该分支中可能与您的包含过滤器匹配的任何文件。因此,您首先复制所需的文件,同时不创建任何空目录。然后复制您想要的任何目录。

$ rsync --recursive --prune-empty-dirs --include="*.txt" --filter="-! */" dir_1 copy_of_dir_1
$ rsync --recursive --include '/dir1/dir2/' --include '/dir3/dir4/' --filter="-! */" dir_1 copy_of_dir_1
Run Code Online (Sandbox Code Playgroud)

如果您不介意指定的目录为空时不会被复制,则可以将它们组合起来:

$ rsync --recursive --prune-empty-dirs --include="*.txt" --include '/dir1/dir2/' --include '/dir3/dir4/' --filter="-! */" dir_1 copy_of_dir_1
Run Code Online (Sandbox Code Playgroud)

--filter="-! */"是必要的,因为 rsync 包括所有与任何过滤器都不匹配的文件和文件夹(将其想象为--include过滤器列表末尾的不可见过滤器)。rsync根据过滤器列表检查要复制的每个项目,并根据它找到的第一个匹配项包含或排除该项目。如果没有匹配项,它会命中那个隐形--include并继续包含该项目。我们想将此默认值更改为--exclude,因此我们添加了一个排除过滤器(-in -! */),然后我们否定匹配(!)并匹配所有目录(*/)。由于这是一个否定匹配,结果是我们允许rsync进入所有目录(正如我之前提到的,允许rsync找到我们想要的文件)。

我们使用--filter代替--exclude作为最终过滤器,因为--exclude不允许使用!运算符指定否定匹配。