比较两个目录以生成输出

时间:2017-12-15 12:45:15

标签: bash unix diff

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

  • 第一个文件将包含文件夹B中比文件夹A更新的文件列表,以及文件夹B中与文件夹A不同/孤儿的文件
  • 第二个文件将包含文件夹A中比文件夹B更新的文件列表,以及文件夹A中与文件夹B不同/孤儿的文件

如何在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

1 个答案:

答案 0 :(得分:2)

目录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 "$3" ]; then # the optional 3rd argument is the output file
  OUTPUT="$3"
else # if it isn't provided, escape path slashes to underscores
  OUTPUT="${2////_}-newer-than-${1////_}"
fi

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

首先,这确定输出文件,该文件来自第三个参数,或者使用替换创建其他输入,以便在存在路径时将斜杠转换为下划线,例如,以{{1}运行将其文件列表输出到当前工作目录中的bash script.bash /usr/local/bin /usr/bin

这将两个命令组合在一起,然后确保它们已排序。不会有任何重复,所以你不必担心(如果有的话,你会使用_usr_local_bin-newer-than-_usr_bin)。

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