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

NVI*_*NVI 69 bash shell scripting command-line sh

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

样品:

html/
  a/
    b.html
  index.html

html_new/
  a/
    b2.html
    b.html
Run Code Online (Sandbox Code Playgroud)

用法:

./mergedirs.sh html html_new
Run Code Online (Sandbox Code Playgroud)

结果:

html/
  a/
    b.html
    b2.html
  index.html
Run Code Online (Sandbox Code Playgroud)

html/a/b.htmlhtml_new/a/b.html
html/a/b2.html复制的被取而代之的是html_new/a/b2.html
html/index.html被保持不变的

Fli*_*imm 80

cp -RT source/ destination/
Run Code Online (Sandbox Code Playgroud)

所有文件和目录都source将以destination.例如,source/file1将被复制到destination/file1.

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

  • 在Mac OS X/darwin上你会想要使用`cp -r source/destination` - 你必须使用/完全按照指示使用它. (5认同)
  • 我认为这个解决方案是因为它与.dotfiles一样"按原样"工作. (2认同)

Luk*_*rer 79

你可能只是想cp -R $1/* $2/- 这是一个递归副本.

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


Car*_*rlG 17

看看rs rsync

rsync --recursive html/ html_new/
Run Code Online (Sandbox Code Playgroud)

Rsync设置了很多标志,所以请查看rsync手册页以获取详细信息


小智 6

只需使用rsync - 除了远程复制之外,它还是本地文件复制和合并的绝佳工具.

rsync -av /path/to/source_folder/ /path/to/destination_folder/
Run Code Online (Sandbox Code Playgroud)

请注意,源文件夹上的尾部斜杠是仅将source_folder的内容复制到目标所必需的.如果你把它关掉,它会复制source_folder 及其内容,因为你想要合并文件夹,这可能不是你想要的.


row*_*rpe 6

尽管这个问题及其公认的答案很古老,但我还是添加了我的答案,因为目前存在的答案cp要么不处理某些边缘情况,要么需要交互工作。通常,边缘情况/可编写性/可移植性/多源并不重要,在这种情况下,简单性获胜,最好直接使用cp较少的标志(如其他答案)来减少认知负荷 - 但对于其他时候(或者对于一个强大的可重用函数)这个调用/函数很有用,顺便说一句,它不是特定于 bash 的(我意识到这个问题是关于 bash 的,所以在这种情况下这只是一个额外的好处)。有些标志可以缩写(例如,使用),但为了解释起见,-a我已将所有标志明确以长格式包含(除了,见下文)。-R显然,如果有一些您特别想要的功能(或者您使用的是非 posix 操作系统,或者您的版本cp不处理该标志 - 我在 GNU coreutils 8.25 上对此进行了测试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 ...]
Run Code Online (Sandbox Code Playgroud)

解释:

  • -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如果出现错误则返回

顺便提一句:

  • 我也在我的系统上使用了一个时髦的新标志,--reflink=auto用于执行所谓的“轻量复制”(写时复制,具有与硬链接相同的速度优势,以及相同的大小优势,直到 和 成反比)未来文件的差异有多大)。该标志在最新的 GNU 中被接受cp,并且在最新的 Linux 内核上不仅仅对兼容文件系统执行无操作。YMWV 在其他系统上有很多。