好的,我的linux文件夹中有两个相关的列表:
/tmp/oldList
/tmp/newList
我需要比较这些列表以查看添加了哪些行以及删除了哪些行。然后,我需要遍历这些行并根据它们是否被添加或删除来对它们执行操作。
我如何在bash中执行此操作?
答案 0 :(得分:58)
使用comm(1)
命令比较两个文件。它们都需要进行排序,如果它们很大,您可以事先进行排序,或者您可以使用bash 进程替换进行内联。
comm
可以结合使用标记-1
,-2
和-3
来指示要禁止行的文件(文件1唯一,文件2唯一或两者都很常见。
仅在旧文件中获取行:
comm -23 <(sort /tmp/oldList) <(sort /tmp/newList)
仅在新文件中获取行:
comm -13 <(sort /tmp/oldList) <(sort /tmp/newList)
您可以将其输入while read
循环来处理每一行:
while read old ; do
...do stuff with $old
done < <(comm -23 <(sort /tmp/oldList) <(sort /tmp/newList))
和新线类似。
答案 1 :(得分:5)
答案 2 :(得分:3)
如果脚本需要可读性,请考虑使用Ruby。
仅在旧文件中获取行:
ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')"
仅在新文件中获取行:
ruby -e "puts File.readlines('/tmp/newList') - File.readlines('/tmp/oldList')"
您可以将其输入到while循环中以处理每一行:
while read old ; do
...do stuff with $old
done < ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')"
答案 3 :(得分:1)
这是旧的,但为了完整起见,我们应该说如果你有一个非常大的集合,最快的解决方案是使用diff生成一个脚本然后获取它,如下所示:
#!/bin/bash
line_added() {
# code to be run for all lines added
# $* is the line
}
line_removed() {
# code to be run for all lines removed
# $* is the line
}
line_same() {
# code to be run for all lines at are the same
# $* is the line
}
cat /tmp/oldList | sort >/tmp/oldList.sorted
cat /tmp/newList | sort >/tmp/newList.sorted
diff >/tmp/diff_script.sh \
--new-line-format="line_added %L" \
--old-line-format="line_removed %L" \
--unchanged-line-format="line_same %L" \
/tmp/oldList.sorted /tmp/newList.sorted
source /tmp/diff_script.sh
更改的行将显示为已删除并已添加。如果您不喜欢这样,可以使用--changed-group-format。检查diff手册页。
答案 4 :(得分:0)
您是否尝试过diff
$ diff /tmp/oldList /tmp/newList
$ man diff
答案 5 :(得分:0)
我通常使用:
diff /tmp/oldList /tmp/newList | grep -v "Common subdirectories"
grep -v
选项反转匹配:
-v,--invert-match 选定的行是与任何指定的样式都不匹配的行。 燕鸥。
因此,在这种情况下,它将获取diff
结果并忽略那些常见的结果。