如何使用 Bash 将一个目录合并到另一个目录中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4572225/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I merge one directory into another using Bash?
提问by NVI
I'm looking for shell script that merge files from one directory into another.
我正在寻找将文件从一个目录合并到另一个目录的 shell 脚本。
Sample:
样本:
html/
a/
b.html
index.html
html_new/
a/
b2.html
b.html
Usage:
用法:
./mergedirs.sh html html_new
Result:
结果:
html/
a/
b.html
b2.html
index.html
html/a/b.html
was replaced by html_new/a/b.html
html/a/b2.html
was copied from html_new/a/b2.html
html/index.html
was kept untouched
html/a/b.html
被替换为html_new/a/b.html
html/a/b2.html
被复制自html_new/a/b2.html
html/index.html
保持不变
回答by Flimm
cp -RT source/ destination/
All files and directories in source
will end up in destination
. For example, source/file1
will be copied to destination/file1
.
中的所有文件和目录都source
将以destination
. 例如,source/file1
将复制到destination/file1
.
The -T
flag stops source/file1
from being copied to destination/source/file1
instead. (Unfortunately, cp
on macOS does not support the -T
flag.)
该-T
标志不再source/file1
被复制到destination/source/file1
。(遗憾的是,cp
在 macOS 上不支持该-T
标志。)
回答by Luke Maurer
You probably just want cp -R $1/* $2/
— that's a recursive copy.
您可能只是想要cp -R $1/* $2/
- 这是一个递归副本。
(If there might be hidden files (those whose names begin with a dot), you should prefix that command with shopt -s dotglob;
to be sure they get matched.)
(如果可能存在隐藏文件(名称以点开头的文件),您应该在该命令前加上前缀shopt -s dotglob;
以确保它们匹配。)
回答by CarlG
Take a look att rsync
看看 rsync
rsync --recursive html/ html_new/
Rsync got alot of flags to set so look at rsync manpage for details
Rsync 需要设置很多标志,请查看 rsync 联机帮助页了解详细信息
回答by Gavster
Just use rsync - it's a great tool for local file copy and merging in addition to remote copying.
只需使用 rsync - 除了远程复制之外,它还是本地文件复制和合并的绝佳工具。
rsync -av /path/to/source_folder/ /path/to/destination_folder/
Note that the trailing slash on the source folder is necessary to copy only the contents of source_folder to the destination. If you leave it off, it will copy the source_folder andit's contents, which is probably not what you are looking for since you want to merge folders.
请注意,源文件夹上的尾部斜杠是仅将 source_folder 的内容复制到目标所必需的。如果您不使用它,它将复制 source_folder及其内容,这可能不是您要查找的内容,因为您要合并文件夹。
回答by rowanthorpe
Even though this question and its accepted answer are ancient, I am adding my answer because the presently existing ones using cp
either don't handle some edge-cases or require working interactively. Often edge-cases/scriptability/portability/multiple-sources don't matter though, in which case simplicity wins, and it is better to use cp
directly with less flags (as in other answers) to reduce cognitive load - but for those othertimes (or for a robustly reusable function) this invocation/function is useful, and incidentally isn't bash-specific (I realise this question was about bash though, so that's just a bonus in this case). Some flags can be abbreviated (e.g. with -a
), but I have included all explicitly in long-form (except for -R
, see below) for the sake of explanation. Obviously just remove any flags if there is some feature you specifically don'twant (or you are on a non-posix OS, or your version of cp
doesn't process that flag - I tested this on GNU coreutils 8.25's cp
):
尽管这个问题及其公认的答案很古老,但我还是要添加我的答案,因为目前使用的答案cp
要么不处理某些边缘情况,要么需要交互工作。通常边缘情况/脚本性/可移植性/多源并不重要,在这种情况下,简单性获胜,最好cp
直接使用较少的标志(如在其他答案中)以减少认知负荷 - 但对于其他时间(或者对于一个健壮的可重用函数)这个调用/函数很有用,顺便说一句,它不是特定于 bash 的(我意识到这个问题是关于 bash 的,所以在这种情况下这只是一个奖励)。一些标志可以缩写(如用-a
),但我已经包括了所有明确的长篇(除-R
,见下文)以供解释。显然,如果有一些您特别不想要的功能(或者您使用的是非 posix 操作系统,或者您的版本cp
不处理该标志 - 我在 GNU coreutils 8.25 上对此进行了测试),显然只需删除任何标志cp
:
mergedirs() {
_retval=0
_dest=""
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 ...]
Explanation:
解释:
-R
: has subtly different semantics from-r
/--recursive
on some systems (particularly with respect to special files in source dirs) as explained in this answer--no-dereference
: never follow symbolic links in SOURCE--preserve=all
: preserve the specified attributes (default: mode,ownership,timestamps), if possible additional attributes: context, links, xattr, all--force
: if an existing destination file cannot be opened, remove it and try again--one-file-system
: stay on this file system--no-target-directory
: treat DEST as a normal file (explained in in this answer, namely: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.
)- [piped input from
yes
]: even with--force
, in this particular recursive modecp
still asks before clobbering each file, so we achieve non-interactiveness by piping output fromyes
to it - [piped output to
/dev/null
]: this is to silence the messy string of questions along the lines ofcp: overwrite 'xx'?
- [return-val & early exit]: this ensures the loop exits as soon as there is a failed copy, and returns
1
if there was an error
-R
:如本答案中所述,与某些系统上的-r
/语义略有不同--recursive
(特别是关于源目录中的特殊文件)--no-dereference
:永远不要遵循 SOURCE 中的符号链接--preserve=all
: 保留指定的属性(默认:模式、所有权、时间戳),如果可能的话附加属性:上下文、链接、xattr、所有--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
] 的管道输入:即使使用--force
,在这种特定的递归模式下cp
仍然会在破坏每个文件之前询问,因此我们通过管道输出yes
到它来实现非交互性 - [管道输出到
/dev/null
]:这是为了让一连串混乱的问题保持沉默cp: overwrite 'xx'?
- [return-val & early exit]:这确保循环一旦有失败的副本就退出,
1
如果有错误则返回
BTW:
顺便提一句:
- A funky new flag which I also use with this on my system is
--reflink=auto
for doing so-called "light copies" (copy-on-write, with the same speed benefits as hard-linking, and the same size benefits until and in inverse proportion to how much the files diverge in the future). This flag is accepted in recent GNUcp
, and does more than a no-op with compatible filesystems on recent Linux kernels. YMWV-a-lot on other systems.
- 我也在我的系统上使用了一个时髦的新标志,
--reflink=auto
用于进行所谓的“轻拷贝”(写时拷贝,具有与硬链接相同的速度优势,并且相同大小的优势直到和成反比到将来文件有多大差异)。这个标志在最近的 GNU 中被接受cp
,并且在最近的 Linux 内核上对兼容的文件系统做了更多的无操作。YMWV-很多在其他系统上。
回答by DVK
Wouldn't cp -r
work?
会不会cp -r
工作?
cp -r html_new/* html
or (since the first version won't copy ".something" files)
或(因为第一个版本不会复制“.something”文件)
cd html_new; cp -r . ../html
Please note that -r
reads from pipesif any of the files in the copied directory are pipes. To avoid that, use -R
instead.
请注意,如果复制目录中的任何文件是管道,-r
则从管道读取。为避免这种情况,请-R
改用。
回答by Brian Clapper
cd html
cp -r . /path/to/html_new