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

Dav*_*Liu 372 linux cp

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

小智 634

rsync快速简便:

rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude
Run Code Online (Sandbox Code Playgroud)

您可以使用--exclude倍数.

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

  • 它与源文件夹相关.这将排除文件夹源/ .git被复制.rsync -r --exclude'.git'源目标 (44认同)
  • 是关于`sourcefolder`或当前工作目录的`thefoldertoexclude`?谢谢 (31认同)
  • 也许我错了,但我认为在"参数"之前添加"开关"是一个好习惯.此外,rsync报告的手册页 - 可以与"="语法一起使用或不使用.因此,对于操作系统的标准化,我使用`rsync -av --progress --exclude ="thefoldertoexclude"sourcefolder/destinationfolder` - 无论如何都要为rsync而不是find查找,因为您可以轻松地使用源的绝对路径而在发现它时更麻烦,因为它在dst中使用`{}`. (15认同)
  • `--exclude /node_modules/` 将排除源树中任何位置的 node_modules。在复制一堆 JavaScript/Node.js 项目文件夹时非常强大。 (6认同)
  • 同意,你无法击败`--exclude`的简单和力量 (3认同)
  • @XaviMontero,如果你想排除多个文件夹,你可以像这样使用 rsync rsync -av --progress --exclude={"thefoldertoexclude","anotherfolder","folder2"} sourcefolder /destinationfolder (2认同)

uli*_*tko 79

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

庆典

链接到手册,搜索extglob.

例:

$ 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的

链接到手册,"文件名生成"部分.

你可以做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.有关详细信息,请参阅联机帮助页.


新!

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

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

奖金专业提示

输入cp *,点击CtrlX*,看看会发生什么.我保证这没有害处

  • 不错的亲提示!这样,您可以轻松删除单个项目。非常感谢! (2认同)
  • 顺便说一句,要关闭 Bash 中的扩展模式匹配功能,请运行“setopt -u extglob”。 (2认同)

Lin*_*een 45

为什么rsync在你能做的时候使用:

find . -type f -not -iname '*/not-from-here/*' -exec cp '{}' '/dest/{}' ';'
Run Code Online (Sandbox Code Playgroud)

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

  • 我认为你需要`-path`参数来测试路径层次结构,而不是-iname (7认同)
  • @Henning 为什么不是`rsync`?因为它可能不存在于系统中!而`find`,`cp`总是在他们的位置上。或者你是那种安装 2gigs 的东西来做简单事情的人? (3认同)
  • 你最后还需要一个分号:`find.-type f -not -path'*/not-from-here/*' - exec cp'{}''/ dest/{}'\;` (2认同)

小智 36

cp -r `ls -A | grep -v "c"` $HOME/
Run Code Online (Sandbox Code Playgroud)

  • 因目录带有空格而失败 (3认同)

sec*_*rve 23

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

shopt -s extglob
cp -r !(Filename1 | FoldernameX | Filename2) Dest/
Run Code Online (Sandbox Code Playgroud)

  • 对我不起作用.我得到`-bash:!:event not found` (8认同)
  • shopt -s extglob(执行此命令以启用!in cp,rm等) (7认同)

小智 11

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

cd dotfiles
tar -c --exclude .git --exclude README . | tar -x -C ~/dotfiles2
Run Code Online (Sandbox Code Playgroud)


小智 8

rsync的

rsync -r --verbose --exclude 'exclude_pattern' ./* /to/where/
Run Code Online (Sandbox Code Playgroud)

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

  • 与最佳答案相比有什么区别/改进? (2认同)

lam*_*345 8

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

mkdir .hiddendir
cp * .hiddendir -R
mv .hiddendir realdirname
Run Code Online (Sandbox Code Playgroud)


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


小智 8

它相对于源目录。
这将从source/.git复制目录中排除该目录。

rsync -r --exclude '.git' source target
Run Code Online (Sandbox Code Playgroud)


Van*_*ril 7

我假设你正在使用bash或dash.这会有用吗?

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

做一个不包含您不想要的文件的ls,并将其作为cp的第一个参数

  • 你可以跳过额外的`ls`并简单地做`cp!(file1 | file1)dest`. (9认同)

ehu*_*kai 6

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


sud*_*ork 5

cp -rv `ls -A | grep -vE "dirToExclude|targetDir"` targetDir
Run Code Online (Sandbox Code Playgroud)

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

  • 注意包含空格的目录条目。 (4认同)

Mil*_*mek 5

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

这个命令对我有用:

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

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