576

我想复制目录中的所有文件,但特定子目录中的某些文件除外。我注意到该cp命令没有该--exclude选项。那么,我该如何实现呢?

4

20 回答 20

970

rsync快速简单:

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

您可以--exclude多次使用。

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

请注意,选项thefoldertoexclude后的 dir--exclude是相对于 的sourcefolder,即sourcefolder/thefoldertoexclude.

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

于 2013-02-09T15:04:45.373 回答
114

好吧,如果每个 unix-ish 文件实用程序(如 cp、mv、rm、tar、rsync、scp ......)都必须排除某些文件名模式,那么就会发生巨大的重复工作。相反,这些事情可以作为globbing的一部分来完成,即通过你的 shell。

重击

man 1 bash, / extglob

例子:

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

所以你只需在里面放一个模式!(),它就会否定匹配。该模式可以任意复杂,从枚举单个路径(如 Vanwaril 在另一个答案中所示)开始!(filename1|path2|etc3),到带有星号和字符类的类似正则表达式的东西。有关详细信息,请参阅手册页。

zsh

man 1 zshexpn,/ 文件名生成

您可以执行setopt KSH_GLOB和使用类似 bash 的模式。或者,

% setopt EXTENDED_GLOB
% 回声图像/*
images/004.bmp images/033.jpg images/1276338351183.jpg images/2252.png
% 回显图像/*~*.jpg
图像/004.bmp 图像/2252.png

所以x~y匹配模式x,但不包括模式y。再一次,有关完整的详细信息,请参阅联机帮助页。


新!

鱼壳对此有一个更漂亮的答案

cp (string match -v '*.excluded.names' -- srcdir/*) destdir

奖金专业提示

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

于 2011-11-11T00:53:20.263 回答
60

为什么rsync在可以做到的时候使用:

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

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

于 2011-01-03T16:04:39.073 回答
44
cp -r `ls -A | grep -v "c"` $HOME/
于 2012-10-19T06:37:13.610 回答
33

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

shopt -s extglob
cp -r !(Filename1 | FoldernameX | Filename2) Dest/
于 2014-02-24T12:59:16.603 回答
21

它是相对于源目录的。
这将排除目录source/.git被复制。

rsync -r --exclude '.git' source target
于 2018-02-28T10:14:19.747 回答
17

扩展mvds 的评论,这对我有用

cd dotfiles
tar -c --exclude .git --exclude README . | tar -x -C ~/dotfiles2
于 2012-06-25T04:46:31.000 回答
9

rsync

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

并首先尝试使用 -n 选项来查看将要复制的内容

于 2013-04-05T04:10:21.917 回答
8

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用于存档模式,这意味着您想要递归并想要保留几乎所有内容。

于 2017-12-09T19:11:27.800 回答
7
cp -rv `ls -A | grep -vE "dirToExclude|targetDir"` targetDir

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

于 2011-01-03T16:00:05.047 回答
7

我假设您使用的是 bash 或 dash。这行得通吗?

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

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

于 2011-01-03T16:07:27.770 回答
5

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

于 2011-01-03T17:21:16.007 回答
4

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

mkdir .hiddendir
cp * .hiddendir -R
mv .hiddendir realdirname
于 2013-06-07T12:20:50.047 回答
3

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

这个命令对我有用:

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

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

于 2013-07-24T10:39:56.837 回答
2
cp -r `ls -A | grep -v "Excluded_File_or_folder"` ../$target_location -v
于 2020-03-31T04:12:57.413 回答
1
mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/
于 2012-03-25T00:22:11.327 回答
1

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

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

我使用上面的方法来复制我的服务器上的所有音乐类型文件,这些文件比我安装在的 Western Digital TV Live Hub 上的文件更新/media/wd。我使用上面是因为我有很多 DVD 文件、mpeg 等要排除,并且由于某种原因 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/
于 2014-05-07T00:30:04.007 回答
1
ls -I "filename1" -I "filename2" | xargs cp -rf -t destdir 

第一部分是ls所有文件,但使用 flag 隐藏特定文件-I。的输出ls用作第二部分的标准输入。从标准输入xargs构建和执行命令。cp -rf -t destdir该标志-r表示递归复制目录,-f表示强制复制文件,这将覆盖 中的文件destdir-t指定目标目录复制到。

于 2019-03-22T02:02:43.460 回答
0

晚了10年。归功于莱纳斯·克莱恩。

我讨厌rsync!;) 那么为什么不使用findandcp呢?并且通过这个答案也mkdir可以创建一个不存在的文件夹结构。

cd /source_folder/ && find . -type d -not -path '*/not-from-here/*' -print -exec mkdir -p '/destination_folder/{}' \;

cd /source_folder/ && find . -type f -not -path '*/not-from-here/*' -print -exec cp -au '{}' '/destination_folder/{}' \;

看起来cdì 有必要将相对路径与find.

mkdir -p将创建所有子文件夹,并且当文件夹已经存在时不会抱怨。


豪斯滕我们有下一个问题。当有人创建一个中间有一个新文件的新文件夹时会发生什么?确切地说:这些新文件将失败。(解决方案:再次运行它!:)) 将所有内容放在一个find命令中的解决方案似乎很困难。


清理:https ://unix.stackexchange.com/q/627218/239596

于 2020-12-28T22:57:04.953 回答
0

2022 年 1 月更新:

这是最简单的方法(并不复杂)。

首先,制作“temp”文件夹

mkdir temp

其次,将原始文件夹中的所有文件复制到“temp”文件夹

“-R”标志可以复制包括“符号链接”在内的所有文件

cp -R originalFolder/. temp/

第三,从“temp”文件夹中删除“myFolder”

rm temp/myFolder

最后,将所有文件从“temp”文件夹复制您的目标文件夹

cp -R temp/. destinationFolder/

此外,这是没有“temp”文件夹的最短方法:

cp -R originalFolder/!(myFolder) destinationFolder/
于 2022-01-12T23:59:45.257 回答