我正在寻找将一个目录中的文件合并到另一个目录的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
{{1}}保持不变
答案 0 :(得分:73)
cp -RT source/ destination/
source
中的所有文件和目录都将以destination
结尾。例如,source/file1
将被复制到destination/file1
。
-T
标记阻止source/file1
被复制到destination/source/file1
。
答案 1 :(得分:71)
您可能只想要cp -R $1/* $2/
- 这是一个递归副本。
(如果可能存在隐藏文件(名称以点开头的文件),则应在该命令前加上shopt -s dotglob;
,以确保它们匹配。)
答案 2 :(得分:15)
看看att rsync
rsync --recursive html/ html_new/
Rsync设置了很多标志,所以请查看rsync联机帮助页以获取详细信息
答案 3 :(得分:6)
只需使用rsync - 除了远程复制之外,它还是本地文件复制和合并的绝佳工具。
rsync -av /path/to/source_folder/ /path/to/destination_folder/
请注意,源文件夹上的尾部斜杠只需将source_folder的内容复制到目标。如果你把它关掉,它会复制source_folder 和它的内容,这可能不是你想要的,因为你想要合并文件夹。
答案 4 :(得分:2)
cp -r
不会有效吗?
cp -r html_new/* html
或(因为第一个版本不会复制“.something”文件)
cd html_new; cp -r . ../html
请注意,如果复制目录中的任何文件都是管道,-r
会从管道读取。为避免这种情况,请改用-R
。
答案 5 :(得分:2)
cd html
cp -r . /path/to/html_new
答案 6 :(得分:2)
尽管这个问题及其接受的答案很古老,但我正在添加我的答案,因为使用cp
的现有答案要么不处理某些边缘情况,要么需要交互式工作。边缘情况/脚本性/可移植性/多源通常不重要,在这种情况下简单性获胜,并且最好直接使用cp
使用较少的标记(如在其他答案中)以减少认知加载 - 但是对于那些其他次(或者对于强大的可重用函数),这个调用/函数很有用,并且顺便说一下,它不是特定于bash的(我知道这个问题是关于bash的,所以在这种情况下,这只是一个奖励)。有些标志可以缩写(例如使用-a
),但为了便于说明,我已将所有标记明确地包含在长格式中(-R
除外,见下文)。显然只要删除任何标记,如果您有一些特别不想想要的功能(或者您使用的是非posix操作系统,或者您的cp
版本没有处理那个标志 - 我在GNU coreutils 8.25' s cp
上测试了这个:
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
:在this answer --recursive
的语义略有不同(特别是源dirs中的特殊文件) >
--no-dereference
:永远不要关注SOURCE中的符号链接--preserve=all
:保留指定的属性(默认:模式,所有权,时间戳),如果可能的话还有其他属性:context,links,xattr,all --force
:如果无法打开现有目标文件,请将其删除并重试--one-file-system
:留在此文件系统--no-target-directory
:将DEST视为普通文件(在this answer中说明,即: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
仍然要求破坏每个文件之前,因此我们通过管道输出来实现非交互性{ {1}}到它yes
]:这是为了使/dev/null
cp: overwrite 'xx'?
顺便说一句:
1
来做所谓的"轻复制" (写时复制,具有与硬链接相同的速度优势,并且相同大小的好处直到与文件在未来分歧的数量成反比)。这个标志在最近的GNU --reflink=auto
中被接受,并且在最近的Linux内核上不仅仅是兼容文件系统的无操作。 YMWV-a-lot在其他系统上。答案 7 :(得分:0)
cp --recursive --no-target-directory [--no-clobber] "[IN]" "[OUT]"
--no-target-directory
:将 OUT 视为普通文件,因此包含以 dot 开头的文件(隐藏文件)。
--no-clobber
:如果您不想覆盖现有文件。无论如何,内部目录永远不会被覆盖。