比较两个目录以产生输出

Comparing two directories to produce output

我正在编写一个 Bash 脚本,它将文件夹 A(源)中的文件替换为文件夹 B(目标)。但在此之前,我想录制2个文件。

如何在 Bash 中完成此操作?我试过使用 diff -qr 但它会产生以下输出:

Files old/VERSION and new/VERSION differ
Files old/conf/mime.conf and new/conf/mime.conf differ
Only in new/data/pages: playground
Files old/doku.php and new/doku.php differ
Files old/inc/auth.php and new/inc/auth.php differ
Files old/inc/lang/no/lang.php and new/inc/lang/no/lang.php differ
Files old/lib/plugins/acl/remote.php and new/lib/plugins/acl/remote.php differ
Files old/lib/plugins/authplain/auth.php and new/lib/plugins/authplain/auth.php differ
Files old/lib/plugins/usermanager/admin.php and new/lib/plugins/usermanager/admin.php differ

我也试过这个

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

但它没有给我所需的结果范围。这里的问题是数据格式不正确,我只希望文件而不是目录显示在文本文件中,例如:

conf/mime.conf
data/pages/playground/
data/pages/playground/playground.txt
doku.php
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

目录 B (new/) 中比目录 A (old/) 更新的文件列表:

find new -newermm old

这仅运行 find 并检查 new/ 的内容,由 -newerXY reference 过滤,XY 都设置为 m(修改时间)和 referenceold 目录本身。

目录 B (new/) 中缺少但存在于目录 A (old/) 中的文件:

A=old B=new
diff -u <(find "$B" |sed "s:$B::") <(find "$A" |sed "s:$A::") \
  |sed "/^+\//!d; s::$A/:"

这会将变量 $A$B 设置为您的目标目录,然后对它们的内容运行统一的 diff(使用 process substitution 定位 find 并删除带有 sed 的目录名称,这样 diff 就不会混淆)。最后的 sed 命令首先匹配添加项(以 +/ 开头的行),修改它们以将 +/ 替换为目录名和斜杠,然后打印它们(其他行是已删除)。

这是将创建文件的 bash 脚本:

#!/bin/bash
# Usage: bash script.bash OLD_DIR NEW_DIR [OUTPUT_FILE]
# compare given directories

if [ -n "" ]; then # the optional 3rd argument is the output file
  OUTPUT=""
else # if it isn't provided, escape path slashes to underscores
  OUTPUT="${2////_}-newer-than-${1////_}"
fi

{
  find "" -newermm ""
  diff -u <(find "" |sed "s:::") <(find "" |sed "s:::") \
    |sed "/^+\//!d; s::/:"
} |sort > "$OUTPUT"

首先,这确定了输出文件,它要么来自第三个参数,要么是从其他输入创建的,如果有路径,则使用替换将斜杠转换为下划线,例如,运行 因为 bash script.bash /usr/local/bin /usr/bin 会将其文件列表输出到当前工作目录中的 _usr_local_bin-newer-than-_usr_bin

这会合并这两个命令,然后确保它们已排序。不会有任何重复,所以你不必担心(如果有,你会使用 sort -u)。

您可以通过在调用此脚本时更改参数的顺序来获取第一个和第二个文件。