【问题标题】:Bash script that copies the differences in two directories to a third directory?将两个目录中的差异复制到第三个目录的 Bash 脚本?
【发布时间】:2013-11-16 05:14:31
【问题描述】:

我要做的是比较两个目录 d1 和 d2,并将 d1 和 d2 中都不存在的所有文件复制到第三个目录 d3。

我知道我可以使用以下命令复制两个目录中的所有文件:

cp -vfudp dir1/* dir3/

cp -vfudp dir2/* dir3/

但我知道我需要合并查找功能并进行比较。或差异。我可以使用

rsync -a dir1/ dir2/

以某种方式创建第三个目录并放置差异?

我觉得我需要使用

diff -r --brief dir1 dir2

也在那里的某个地方。我是新手程序员,也是 bash 的新手,因此非常感谢您对函数的解释。

【问题讨论】:

    标签: bash shell


    【解决方案1】:
    for file in $(diff dir1 dir2 | sed 's/Only in \([^ ]*\): /\1\//'); do
        cp "$file" dir3/
    done
    

    diff dir1 dir2 为您提供两个目录中都不存在的文件列表:

    $ diff dir1 dir2
    > Only in dir2: f3
    > Only in dir1: f4
    > Only in dir2: f5
    

    我们通过 管道来获取文件的路径(也许diff 可以选择这样做,而我们不需要

    $ diff dir1 dir2 | sed 's/Only in \([^ ]*\): /\1\//'
    > dir2/f3
    > dir1/f4
    > dir2/f5
    

    然后我们遍历这个文件列表并将它们复制到dir3

    小心子目录! (有吗?)

    让我们仔细看看命令:

    sed 's/Only in \([^ ]*\): /\1\//'
    

    s 是替代命令,例如想用假代替真,你会使用s/true/false/。我们想替换Only in \([^ ]*\):。第一部分只是diff命令的输出文本,然后我们使用转义括号\(\)匹配文件名,以便稍后再次引用它(\1) .在括号内,我们有[^ ]*,它匹配除了空格之外的所有内容(所以这里我们假设文件名没有空格,这可以改进!)。这与目录的名称相匹配。然后我们匹配更多diff 命令的文本,即:。所有这些都替换为\1,这只是\(\)(目录名称)中的一部分。我们最终得到了相关文件的完整路径。

    【讨论】:

    • 感谢您的帖子。我现在正在阅读 sed 以了解更多信息,但我假设没有子目录。第一段代码有道理,我只是不明白这一点:>'s/Only in ([^ ]*): /\1\//'
    • 我添加了对sed 命令的解释。阅读和解释 sed 的语法可能很困难,所以如果你对这个主题感兴趣,我建议你做一个教程。
    【解决方案2】:
    d1="/tmp/d1"
    d2="/tmp/d2"
    d3="/tmp/d3"
    
    cd "${d1}"
    for file in * ; do
        if [ ! -f "${d2}/${file}" ] ; then
            cp "${file}" "${d3}"
        fi
    done
    cd -
    
    cd "${d2}"
    for file in * ; do
        if [ ! -f "${d1}/${file}" ] ; then
            cp "${file}" "${d3}"
        fi
    done
    cd -
    

    【讨论】:

      【解决方案3】:

      使用 的单线解决方案

      LANG=C diff -aqr /tmp/d1 /tmp/d2 |
          awk -F'[ :]' '/^Only in/{system("cp -a "$3"/"$NF " /tmp/d3/")}'
      

      说明

      • LANG=C 强制差异输出为英文以进行错误解析
      • diff -aqr /tmp/d1 /tmp/d2 将递归显示两个目录中丢失或不同的文件
      • 我们使用awk 删除目录/文件名
      • -F'[ :]' 表示:在空格和: 上拆分列
      • '/^Only in/is like agrep`,如果找到模式,我们执行:
      • system("cp -a "$3"/"$NF " /tmp/d3/") : 复制 found_dir/found_file 到 /tmp/d3

      警告

      • 脚本不处理名称中包含空格的文件/目录,这需要额外处理,但您现在有一个良好的开始

      【讨论】:

      • 这个是最短的,你能简单解释一下 awk 在这里做了什么吗?
      猜你喜欢
      • 1970-01-01
      • 2011-07-12
      • 1970-01-01
      • 1970-01-01
      • 2016-08-05
      • 1970-01-01
      • 2014-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多