如何使用“ cp”命令排除特定目录?


Answers:


702

rsync快速简便:

rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude

您可以使用--exclude多次。

rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude --exclude anotherfoldertoexclude

请注意,option thefoldertoexclude之后的dir --exclude相对于sourcefolder,即sourcefolder/thefoldertoexclude

您也可以添加-n空运行以查看执行实际操作之前将复制的内容,如果一切正常,请-n从命令行中删除。


3
同意,您无法击败--exclude
Matthew的活动

31
thefoldertoexclude相对于sourcefolder当前工作目录还是相对于当前工作目录?谢谢
Beebee

46
它相对于源文件夹。这将不复制文件夹source / .git。rsync -r-排除“ .git”源目标
orkoden 2013年

15
也许我错了,但我认为在“参数”之前添加“开关”是一个好习惯。同样,rsync报告的手册页-不包括是否使用“ =”语法。因此,为了在整个操作系统之间实现标准化,我将使用rsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder-无论如何都要为rsync而不是find投票,因为您可以轻松地为源使用绝对路径,而在find中则很麻烦,因为它{}在dst中使用了。
哈维·蒙特罗

1
@mamun当然,例如,从远程服务器到本地计算机: $ rsync user@example.com:/var/www/mypage /var/www/mylocalpage/或从本地到远程$ rsync /var/www/mylocalpage/ user@example.com:/var/www/mypage
sobi3ch

84

好吧,如果每个unix-ish文件实用程序(例如cp,mv,rm,tar,rsync,scp等)都必须执行某些文件名模式的排除,则将发生巨大的重复劳动。相反,这些事情可以作为globlob的一部分来完成,即通过您的shell。

重击

man 1 bash/ extglob

例:

$ shopt -s extglob
$ echo图片/ *
图片/004.bmp图片/033.jpg图片/1276338351183.jpg图片/2252.png
$ echo images /!(*。jpg)
images / 004.bmp images / 2252.png

因此,您只需要在其中放置一个模式!(),它就会使匹配无效。这种模式可以是任意复杂的,从枚举单个路径(如Vanwaril在另一个答案中所示)开始:!(filename1|path2|etc3)到带有星号和字符类的正则表达式一样的东西。有关详细信息,请参见手册页。

sh

man 1 zshexpn/ 文件名生成

您可以做setopt KSH_GLOB和使用类似bash的模式。要么,

%setopt EXTENDED_GLOB
回声图像百分比/ *
图片/004.bmp图片/033.jpg图片/1276338351183.jpg图片/2252.png
%回声图像/*~*.jpg
images / 004.bmp images / 2252.png

因此x~y匹配模式x,但不包括模式y。同样,有关完整详细信息,请参见联机帮助页。


新!

外壳有一个更漂亮的回答这个:

🐟cp(字符串匹配-v'* .excluded.names'-srcdir / *)destdir

奖金亲提示

键入cp *,点击,CtrlX*然后看看会发生什么。我保证这不是有害的


@MikhailGolubtsov也许是因为遍历不是递归的,一次只能工作一个级别。编辑出来。PS:zsh虽然可以。
ulidtko 2015年

3
不错的亲提示!这样,您可以轻松删除单个项目。非常感谢!
太妃糖'18年

BTW,要关闭Bash中的扩展模式匹配功能,请运行setopt -u extglob
Rockallite

49

rsync何时可以使用,为什么使用:

find . -type f -not -iname '*/not-from-here/*' -exec cp '{}' '/dest/{}' ';'

这假定目标目录结构与源目录的结构相同。


8
我认为您需要-path参数来测试路径层次结构,而不是-iname
James Murty 2012年

3
最后,您还需要用分号:find . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
Matthew Wilcoxson

1
哇,它不会让我:“编辑必须至少包含6个字符”!
马修·威尔考克斯森

1
@MatthewWilcoxson Meh。一旦获得更多代表,这些限制将被取消。我相应地编辑了答案。再次感谢!
Linus Kleen

1
@亨宁为什么不rsync呢?因为它可能不存在于系统中!而findcp总是在他们的位置上。还是您是从安装2gig东西来做简单事情的家伙中选出来的?
Reishin

37
cp -r `ls -A | grep -v "c"` $HOME/

1
在Windows 10 .sh中为我工作
atwellpub

制作了一个shell函数,该函数简化了自定义源路径的使用以及仅排除一个文件或目录的使用: # $1 = source path # $2 = destination path # $3 = filter copy_from_source_to_destination_except_filter() { cp -r $(ls -A $1 | grep -v -w $3 | awk -v path=$1 '{printf "%s/%s ", path, $1}') $2 }
ElectRocnic

失败,目录与空间
塞尔吉奥

27

我找到的最简单的方法是,只需在括号中添加文件和文件夹的名称,即可复制除文件和文件夹之外的所有文件:

shopt -s extglob
cp -r !(Filename1 | FoldernameX | Filename2) Dest/

9
对我不起作用。我得到了-bash: !: event not found
geneorama

8
shopt -s extglob(执行此操作以在cp,rm等中启用!)
imkost 2014年



8

同步

rsync -r --verbose --exclude 'exclude_pattern' ./* /to/where/

首先使用-n选项尝试一下,看看将要复制什么


与最佳答案相比有什么区别/改进?
减少活动

7

我假设您正在使用bash或破折号。这行得通吗?

shopt -s extglob  # sets extended pattern matching options in the bash shell
cp $(ls -laR !(subdir/file1|file2|subdir2/file3)) destination

进行ls排除不需要的文件,并将其用作cp的第一个参数


9
您可以跳过多余的操作,ls而只需执行cp !(file1|file1) dest
肖恩·钦

不要使用-laR。它添加了干扰cp的字符串。 cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
LAL 2015年

5

另一个更简单的选项是安装和使用具有--exclude-dir选项的rsync,该同步可用于本地和远程文件。


4

rsync实际上非常棘手。必须进行多次测试才能使其正常工作。

假设您要复制/var/www/html到目录,/var/www/dev但可能由于目录大小而需要排除 /var/www/html/site/video/目录。该命令将是:

rsync -av --exclude 'sites/video' /var/www/html/ /var/www/dev

一些警告

  1. 最后一个斜杠 /源代码中是必需的,否则它将复制源目录而不是其目录,并变为/var/www/dev/html/xxxx,这可能不是您想要的。
  2. 所述的--exclude路径是相对直接的来源。即使您输入完整的绝对路径,它也不起作用。

  3. -v用于冗长,-a用于存档模式,这意味着您需要递归并希望保留几乎所有内容。


一个简单的解决方案,采取的特殊字符和空格的烦恼
塞尔吉奥

感谢您解释参数,与当前的最佳答案不同!
减少活动

3
cp -rv `ls -A | grep -vE "dirToExclude|targetDir"` targetDir

编辑:忘记也排除目标路径(否则它将递归复制)。


4
注意包含空格的目录条目。
Paulo Scardine 2011年

3

这是Linus Kleen答案的修改。他的回答对我没有用,因为会有一个。添加在cp不喜欢的文件路径的前面(该路径看起来像source / .destination / file)。

这个命令对我有用:

find . -type f -not -path '*/exlude-path/*' -exec cp --parents '{}' '/destination/' \;

--parents命令保留目录结构。


2

只需将其暂时移动到隐藏目录中即可(如果需要,可以在之后将其重命名)。

mkdir .hiddendir
cp * .hiddendir -R
mv .hiddendir realdirname

1
可能不太漂亮-但这是我在这里找到的唯一可与cp标准POSIX shell 配合使用的选项sh
tomekwi's

1
这个答案被大大低估了。这是最兼容,最容易阅读和易于理解的答案。荣誉,我不知道为什么我没有想到它。
罗伯特·塔拉达

谢谢@RobertTalada,答案将从现在走多远?️‍🌈
lama12345


0

我使用“ do while”循环来读取find命令的输出。在此示例中,我要匹配(而不是排除)某些模式,因为我想要的模式匹配数量比我不想要的要少得多。您可以在-iname标志前面使用-not来反转逻辑:

    find . -type f -iname "*.flac" -o -print0 -iname "*.mp3" -print0 -o -iname "*.wav" -print0 -o -iname "*.aac" -print0 -o -iname "*.wma" -print0 | while read -d $'\0' file; do cp -ruv "$file" "/media/wd/network_sync/music/$file"; done

我使用上面的命令复制服务器上比/ media / wd上安装的Western Digital TV Live Hub上新的所有音乐类型文件。我使用上面的是因为我有很多DVD文件,mpeg等要排除的AND,因为某种原因rsync看起来像是正在复制,但是在看wd设备后,尽管没有,但文件不存在使用此命令在rsync期间出错:

    rsync -av --progress --exclude=*.VOB --exclude=*.avi --exclude=*.mkv --exclude=*.ts --exclude=*.mpg --exclude=*.iso --exclude=*ar --exclude=*.vob --exclude=*.BUP --exclude=*.cdi --exclude=*.ISO --exclude=*.shn --exclude=*.MPG --exclude=*.AVI --exclude=*.DAT --exclude=*.img --exclude=*.nrg --exclude=*.cdr --exclude=*.bin --exclude=*.MOV --exclude=*.goutputs* --exclude=*.flv --exclude=*.mov --exclude=*.m2ts --exclude=*.cdg --exclude=*.IFO --exclude=*.asf --exclude=*.ite /media/2TB\ Data/data/music/* /media/wd/network_sync/music/

0
ls -I "filename1" -I "filename2" | xargs cp -rf -t destdir 

第一部分ls所有文件,但带有标志的隐藏特定文件-I。的输出ls用作第二部分的标准输入。xargs建立并执行命令cp -rf -t destdir从标准输入生成。标记-r表示递归复制目录,-f表示强制复制文件,它将覆盖中的文件destdir-t指定目标目录的副本。


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.