如何使用Bash将一个目录合并到另一个目录中?

我正在寻找合并文件从一个目录到另一个的shell脚本。

样品:

html/ a/ b.html index.html html_new/ a/ b2.html b.html 

用法:

 ./mergedirs.sh html html_new 

结果:

 html/ a/ b.html b2.html index.html 

html/a/b.htmlhtml_new/a/b.html所取代
html/a/b2.html是从html_new/a/b2.html复制的
html/index.html保持不变

你可能只是想要cp -R $1/* $2/ – 这是一个recursion的副本。

(如果可能存在隐藏文件(名称以点开头的文件),应该在命令前加上shopt -s dotglob;以确保它们匹配。)

 cp -RT source/ destination/ 

source文件中的所有文件和目录都将在destination结束。 例如, source/file1将被复制到destination/file1

-T标志停止将source/file1复制到destination/source/file1

看看rsync

 rsync --recursive html/ html_new/ 

Rsync有很多的标志设置,所以看看rsync手册页的细节

只需使用rsync – 除了远程复制之外,这是本地文件复制和合并的好工具。

rsync –av / path / to / source_folder / / path / to / destination_folder /

请注意,源文件夹的尾部斜线是必须的,只将source_folder的内容复制到目的地 – 如果您不closures它,它将复制source_folder 及其内容 – 可能不是您要查找的内容,因为您要合并文件夹。

 cd html cp -r . /path/to/html_new 

不会cp -r工作?

 cp -r html_new/* html 

或者(因为第一个版本不会复制“.something”文件)

 cd html_new; cp -r . ../html 

请注意,如果复制目录中的任何文件都是pipe道,则-r 会从pipe道中读取数据 。 为了避免这种情况,请使用-R代替。

尽pipe这个问题及其被接受的答案是古老的,但是我join了我的答案,因为现有的使用cp或者不能处理一些边界情况或者需要交互工作。 通常情况下,edge-cases / scriptability / portability / multiple-sources并不重要,在这种情况下,简单性是胜利的,最好是使用更less的标志直接使用cp来减less认知负担。 (或强大的可重用函数)这个调用/函数是有用的,顺便说一句,不是特定于bash(我知道这个问题是关于bash,所以这只是在这种情况下的奖金)。 有些标志可以缩写(例如-a ),但是为了解释的缘故,我已经将所有的标志全部明确地包含在长格式中( -R除外,参见下文)。 显然,只要删除了任何标志,如果有一些你特别想要的function(或者你在非POSIX操作系统,或者你的版本的cp不处理该标志 – 我在GNU coreutils 8.25的cp上testing过) :

 mergedirs() { _retval=0 _dest="$1" shift yes | \ for _src do cp -R --no-dereference --preserve=all --force --one-file-system \ --no-target-directory "${_src}/" "$_dest" || { _retval=1; break; } done 2>/dev/null return $_retval } mergedirs destination source-1 [source-2 source-3 ...] 

说明:

  • -R :在某些系统上具有与-r / – --recursive微妙不同的语义(特别是关于源码目录中的特殊文件)
  • --no-dereference :从不遵循SOURCE中的符号链接
  • --preserve=all :保留指定的属性(默认:模式,所有权,时间戳),如果可能的话附加属性:context,links,xattr,all
  • --force :如果现有的目标文件无法打开,请将其删除并重试
  • --one-file-system :留在这个文件系统
  • --no-target-directory :把DEST当成一个普通的文件(在这个回答中解释过,即: If you do a recursive copy and the source is a directory, then cp -T copies the content of the source into the destination, rather than copying the source itself.
  • [从yesinput]:即使使用了--force ,在这个特定的recursion模式下, cp仍然在每个文件打开之前仍然要求,所以我们通过从yes输出yes来实现非交互性
  • [输出到/dev/null ]:这是为了按照cp: overwrite 'xx'?这个语句来消除杂乱的问题串cp: overwrite 'xx'?
  • [return-val&early exit]:这确保循环一旦失败的副本就退出,如果发生错误,返回1

BTW:

  • 一个时髦的新标志,我也用这个在我的系统上是 – --reflink=auto做所谓的“光副本”(copy-on-write,具有与硬链接相同的速度好处,和相同的大小好处直到与将来文件分歧的程度成反比)。 这个标志在最近的GNU cp是可以接受的,而且在最近的Linux内核上没有兼容的文件系统。 在其他系统上的YMWV-a-lot。