比较两个目录以产生输出
Comparing two directories to produce output
我正在编写一个 Bash 脚本,它将文件夹 A(源)中的文件替换为文件夹 B(目标)。但在此之前,我想录制2个文件。
- 第一个文件将包含文件夹 B 中比文件夹 A 新的文件列表,以及文件夹 B 中 different/orphans 相对于文件夹 A
的文件
- 第二个文件将包含文件夹 A 中比文件夹 B 新的文件列表,以及文件夹 A 中 different/orphans 相对于文件夹 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
目录 B (new/
) 中比目录 A (old/
) 更新的文件列表:
find new -newermm old
这仅运行 find
并检查 new/
的内容,由 -newerXY reference
过滤,X
和 Y
都设置为 m
(修改时间)和 reference
是 old
目录本身。
目录 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
)。
您可以通过在调用此脚本时更改参数的顺序来获取第一个和第二个文件。
我正在编写一个 Bash 脚本,它将文件夹 A(源)中的文件替换为文件夹 B(目标)。但在此之前,我想录制2个文件。
- 第一个文件将包含文件夹 B 中比文件夹 A 新的文件列表,以及文件夹 B 中 different/orphans 相对于文件夹 A 的文件
- 第二个文件将包含文件夹 A 中比文件夹 B 新的文件列表,以及文件夹 A 中 different/orphans 相对于文件夹 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
目录 B (new/
) 中比目录 A (old/
) 更新的文件列表:
find new -newermm old
这仅运行 find
并检查 new/
的内容,由 -newerXY reference
过滤,X
和 Y
都设置为 m
(修改时间)和 reference
是 old
目录本身。
目录 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
)。
您可以通过在调用此脚本时更改参数的顺序来获取第一个和第二个文件。