如何复制目录结构但仅包含某些文件
我在 Windows 中找到了问题的解决方案,但我使用的是 Ubuntu:如何使用 Windows 批处理文件复制目录结构但仅包含某些文件?
正如标题所说,如何递归复制一个目录结构但只包含一些文件?例如,给定以下目录结构:
folder1
folder2
folder3
data.zip
info.txt
abc.xyz
folder4
folder5
data.zip
somefile.exe
someotherfile.dll
文件 data.zip 和 info.txt 可以出现在目录结构中的任何位置。如何复制完整的目录结构,但仅包含名为 data.zip
和 info.txt
的文件(所有其他文件应被忽略)?
生成的目录结构应如下所示:
copy_of_folder1
folder2
folder3
data.zip
info.txt
folder4
folder5
data.zip
你能告诉我 Ubuntu 的解决方案吗?
I found a solution for my question in Windows but I'm using Ubuntu: How to copy a directory structure but only include certain files using Windows batch files?
As the title says, how can I recursively copy a directory structure but only include some files? For example, given the following directory structure:
folder1
folder2
folder3
data.zip
info.txt
abc.xyz
folder4
folder5
data.zip
somefile.exe
someotherfile.dll
The files data.zip and info.txt can appear everywhere in the directory structure. How can I copy the full directory structure, but only include files named data.zip
and info.txt
(all other files should be ignored)?
The resulting directory structure should look like this:
copy_of_folder1
folder2
folder3
data.zip
info.txt
folder4
folder5
data.zip
Could you tell me a solution for Ubuntu?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
发布评论
评论(5)
tar
在这个领域是一个非常有用的工具。下面我告诉它c
创建一个v
文件到stdout (-
),获取文件列表从 find
在子 shell ($( ... )
) 中运行,然后将该流通过管道传输到 tar
中,再次要求它 ex
将文件拖到目标目录(-C 〜/目的地
)。
假设目标目录为空。如果不是,那么您只会更新与查找匹配的文件,与 ~/destination
相比,~/source
中缺少的文件不会被删除。
要使用它,请从源目录开始:
bob@home:~$ cd source
bob@home:~/source$ tar cvf - $( find -name "info.txt" -o -name "data.zip" ) | tar x -C ~/destination
这是 ~/source
的内容:
bob@home:~/source$ find
.
./file-i-dont-want
./info.txt
./data.zip
./folder1
./folder1/folder2
./folder1/folder2/another-trashy-file
./folder1/folder2/data.zip
./folder1/info.txt
请注意,find
中的 -o
开关表示 或。
这是操作后目的地的内容:
bob@home:~/destination$ find
.
./info.txt
./data.zip
./folder1
./folder1/folder2
./folder1/folder2/data.zip
./folder1/info.txt
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
要排除
dir3
,无论它在树中的位置如何(即使它包含与--include
匹配的文件):排除
dir3
> 仅在树中的特定位置,指定从源目录开始的绝对路径:仅当
dir3
位于dir2
中时排除它,但无论dir3
位于何处dir2
is:也可以使用通配符在路径元素中,其中
*
表示具有任意名称的目录,**
表示多个嵌套目录。要仅指定要包含的文件和目录,请运行两个 rsync,一个用于文件,另一个用于目录。在单个 rsync 中完成此操作的问题是,当您不包含目录时,rsync 将不会进入该目录,因此不会发现任何文件在该分支中可能与您的包含过滤器匹配。因此,您首先复制所需的文件,同时不创建任何空目录。然后复制您想要的任何目录。
如果您不介意指定的目录为空时不会被复制,您可以将它们组合起来:
--filter="-! */"
是必要的,因为 rsync 包含所有文件以及与任何过滤器均不匹配的文件夹(将其想象为过滤器列表末尾的不可见的--include
过滤器)。rsync
根据过滤器列表检查要复制的每个项目,并根据找到的第一个匹配项包含或排除该项目。如果没有匹配项,它会命中不可见的--include
并继续包含该项目。我们想将此默认值更改为--exclude
,因此我们添加了一个排除过滤器(-! */
中的-
),然后我们否定匹配 (!
) 并匹配所有目录 (*/
)。由于这是一个否定匹配,结果是我们允许 rsync 进入所有目录(正如我之前提到的,这允许 rsync 找到我们想要的文件) 。我们使用
--filter
而不是--exclude
作为最终过滤器,因为--exclude
不允许使用指定否定匹配!
运算符。To exclude
dir3
regardless of where it is in the tree (even if it contains files that would match the--include
s):To exclude
dir3
only at at specific location in the tree, specify an absolute path, starting from your source dir:To exclude
dir3
only when it's indir2
, but regardless of wheredir2
is:Wildcards can also be used in the path elements where
*
means a directory with any name and**
means multiple nested directories.To specify only files and dirs to include, run two
rsync
s, one for the files and one for the dirs. The problem with getting it done in a singlersync
is that when you don't include a dir,rsync
won't enter the dir and so won't discover any files in that branch that may be matching your include filter. So, you start by copying the files you want while not creating any dirs that would be empty. Then copy any dirs that you want.You can combine these if you don't mind that your specified dirs don't get copied if they're empty:
The
--filter="-! */"
is necessary because rsync includes all files and folders that match none of the filters (imagine it as an invisible--include
filter at the end of the list of filters).rsync
checks each item to be copied against the list of filters and includes or excludes the item depending on the first match it finds. If there's no match, it hits that invisible--include
and goes on to include the item. We wanted to change this default to--exclude
, so we added an exclude filter (the-
in-! */
), then we negate the match (!
) and match all dirs (*/
). Since this is a negated match, the result is that we allowrsync
to enter all the directories (which, as I mentioned earlier, allowsrsync
to find the files we want).We use
--filter
instead of--exclude
for the final filter because--exclude
does not allow specifying negated matches with the!
operator.