复制特定文件类型,保持文件夹结构


108

我有一个文件夹结构,其中有一堆* .csv文件分散在文件夹中。现在,我想将所有* .csv文件复制到另一个保留文件夹结构的目标位置。

它的工作方式是:

cp --parents *.csv /target
cp --parents */*.csv" /target
cp --parents */*/*.csv /target
cp --parents */*/*/*.csv /target
...

等等,但是我想用一个命令来做。

Answers:


126

人们为什么拒绝使用find的任何原因-exec?非常方便。

find . -name '*.csv' -exec cp --parents \{\} /target \;

了解您的工具。;-)


62
可能因为这个\ {\} \;
2015年

12
'{}'效果也很好
OrangeDog 2015年

3
尽管-execdir比更加安全-exec,但是简单地将一个替换为另一个并不能保持预期的文件夹结构。
西蒙·希恩

2
尝试使用您的命令复制消息时,为什么会收到消息“省略目录”?
Vicky Dev'9

4
您能解释一下为什么必须在这里放括号吗?
Noumenon

46

您也可以使用rsync它。

$ rsync -a --prune-empty-dirs --include '*/' --include '*.csv' --exclude '*' source/ target/

如果要保留源树中的空目录,请跳过以下--prune-empty-dirs选项:

$ rsync -a --include '*/' --include '*.csv' --exclude '*' source/ target/

如果你希望符号链接,修改日期,文件权限,业主等保存完好,请更换-a与另一组合-rlptgoD。;-)


1
-m是的快捷方式--prune-emty-dirs
Geremia'9

另外,-R可以添加该选项以复制源的父目录结构。(请参阅我的回答。)
Geremia

-R对我有用!谢谢
gigi2

32

您可以在直通模式下使用findcpio

find . -name '*.csv' | cpio -pdm  /target

这将在当前目录及以下目录中找到所有.csv文件,并将它们复制到/ target,以保持根目录为根.

如果您使用

find /path/to/files -name '*.csv' | cpio -pdm /target

它将在/path/to/files以下找到所有文件,并将它们复制到/target/path/to/files以下。


3
我尝试了从上到下的所有答案,这是唯一尝试过的唯一答案
OscarRyz

21

cp命令允许多个源参数:

cp **/*.csv --parents ../target

CAVEAT:我在这里使用递归glob;这是globstarBash 4+和中的选项ksh,并且默认情况下受支持zsh。递归glob 与隐藏的文件和文件夹匹配,某些实现遵循符号链接,而其他实现则不匹配。

如果您的shell不支持递归glob,或者您不想使用它们,则可以执行以下操作:

  • *.csv */*.csv */*/*.csv */*/*/*.csv -当然这是非常多余的,并且需要知道目录结构的深度。
  • $(find . -name '*.csv')-这匹配隐藏的文件和文件夹。find还支持指定是否遵循符号链接,这可能很有用。

这正是我尝试过的(递归glob),它找到了一些但不是全部?很奇怪。使用npm copyfiles脚本时,我得到了完全相同的结果,但是如果我使用find命令,它将找到所有内容...
Randyaa

@Randyaa我需要更多有关未找到哪些文件的详细信息,以帮助您。您可能会在这里找到讨论继续进行有关递归glob的精确行为的讨论。
Kyle Strand'9

1
事实证明,由于某种原因未启用递归glob ...我以前从未遇到过此问题,但我只是在执行shopt -s globstar命令之前立即执行了此操作,因此一切都很好。感谢您的跟进!
兰迪亚

--parents是我一直在寻找的东西。谢谢
乔什

17

这个为我工作:

find -name "*.csv" | xargs cp --parents -t /target


使用最简单的语法的最佳答案。工作正常,很容易记住。在许多情况下find [things] | xargs [do stuff]非常强大。
每天宇航员

同意 与其他答案相比,非常简单。
蒂姆B

1
如果文件名中有空格,则中断
Michele Piccolini

@MichelePiccolini可以使用find -print0和来处理文件名中的空格xargs -0
pasztorpisti

8

假设您要将这个结构从复制./source./destination

cd source
find . -name "*.csv" | xargs tar cvf - | (cd ../destination ; tar xfp -)

我准备将其视为一行,这cd source是内置的shell。


2
我不认为他真的意味着一个命令-只是不必像他的例子那样

tar可以-C选择避免首先更改目录。
巴特

8

rsync的联机帮助页:

-R,-相对

使用相对路径。这意味着在命令行上指定的完整路径名将发送到服务器,而不仅仅是文件名的最后一部分。当您要同时发送多个不同的目录时,此功能特别有用。例如,如果使用此命令:

rsync -av /foo/bar/baz.c remote:/tmp/

...这将在远程计算机上的/ tmp /中创建一个名为baz.c的文件。相反,如果您使用

rsync -avR /foo/bar/baz.c remote:/tmp/

然后将在远程计算机上创建一个名为/tmp/foo/bar/baz.c的文件,并保留其完整路径。这些额外的路径元素称为“隐式目录”(即上例中的“ foo”和“ foo / bar”目录)。

因此,这也将起作用:

rsync -armR --include="*/" --include="*.csv" --exclude="*" /full/path/to/source/file(s) destination/
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.