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

时间:2011-01-03 15:53:53

标签: linux cp

我想复制目录中的所有文件,但特定子目录中的某些文件除外。 我注意到'cp'命令没有--exclude选项。 那么,我怎样才能做到这一点?

19 个答案:

答案 0 :(得分:580)

rsync快速简便:

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

您可以使用--exclude倍数。

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

请注意,thefoldertoexclude选项后的目录--excludesourcefolder相关,即sourcefolder/thefoldertoexclude

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

答案 1 :(得分:74)

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

的bash

Link手动搜索 \ textglob

示例:

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

所以你只需在!()中放置一个模式,它就会否定匹配。模式可以是任意复杂的,从单个路径的枚举开始(如Vanwaril在另一个答案中所示):!(filename1|path2|etc3),与星形和字符类的正则表达式一样。有关详细信息,请参阅联机帮助页。

的zsh

Link到手册,“文件名生成”

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

% setopt EXTENDED_GLOB
% echo images/*
images/004.bmp images/033.jpg images/1276338351183.jpg images/2252.png
% echo images/*~*.jpg
images/004.bmp images/2252.png

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


新!

fish shell对此有一个much prettier answer

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

Bonus pro-tip

键入cp *,按 Ctrl X * ,看看会发生什么。 这是无害的我保证

答案 2 :(得分:42)

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

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

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

答案 3 :(得分:31)

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

答案 4 :(得分:21)

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

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

答案 5 :(得分:10)

扩展mvds’s comment,这对我有用

cd dotfiles
tar -c --exclude .git --exclude README . | tar -x -C ~/dotfiles2

答案 6 :(得分: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的第一个参数

答案 7 :(得分:7)

rsync的

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

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

答案 8 :(得分:6)

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

答案 9 :(得分:3)

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

这个命令对我有用:

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

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

答案 10 :(得分:2)

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

答案 11 :(得分:2)

mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/

答案 12 :(得分:2)

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

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

答案 13 :(得分:1)

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

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

答案 14 :(得分:1)

我使用" 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文件,mpegs等,我想要排除和因为某些原因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/

答案 15 :(得分:1)

一种方法是使用find -0-prune来查找要移动的所有文件和目录,然后使用xargs -0复制每个文件和目录。

答案 16 :(得分:0)

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

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

答案 17 :(得分:0)

cp -r ls -A | grep -v "Excluded_File_or_folder" ../$target_location -v

答案 18 :(得分:0)

晚了十年。感谢 Linus Kleen。

我讨厌rsync! ;) 那么为什么不使用 findcp?并通过此答案 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