如何使用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.html
被html_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.
) - [从
yes
input]:即使使用了--force
,在这个特定的recursion模式下,cp
仍然在每个文件打开之前仍然要求,所以我们通过从yes
输出yes
来实现非交互性 - [输出到
/dev/null
]:这是为了按照cp: overwrite 'xx'?
这个语句来消除杂乱的问题串cp: overwrite 'xx'?
- [return-val&early exit]:这确保循环一旦失败的副本就退出,如果发生错误,返回
1
BTW:
- 一个时髦的新标志,我也用这个在我的系统上是 –
--reflink=auto
做所谓的“光副本”(copy-on-write,具有与硬链接相同的速度好处,和相同的大小好处直到与将来文件分歧的程度成反比)。 这个标志在最近的GNUcp
是可以接受的,而且在最近的Linux内核上没有兼容的文件系统。 在其他系统上的YMWV-a-lot。