我通过执行各种命令获得此输出
d41d8cd98f00b204e9800998ecf8427e 1317522632 /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document.txt
d41d8cd98f00b204e9800998ecf8427e 1317522632 /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy.txt
d41d8cd98f00b204e9800998ecf8427e 1317522632 /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy (2).txt
d41d8cd98f00b204e9800998ecf8427e 1317506438 /home/evan/school_work/unix/Projects/Project2/finddups/.svn/tmp/tempfile.tmp
2430ffcf28e7ef6990e46ae081f1fb08 1317522636 /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2 - Copy.txt
2430ffcf28e7ef6990e46ae081f1fb08 1317506569 /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2.txt
我想通过awk管它以使它看起来像这样
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document.txt
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy.txt
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy (2).txt
Original: /home/evan/school_work/unix/Projects/Project2/finddups/.svn/tmp/tempfile.tmp
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2 - Copy.txt
Original: /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2.txt
有什么想法吗?
一些澄清:
换行符或EOF之前的最后一个文件将是原始文件,之前的所有内容都应标记为重复文件。
第一列是文件的md5sum,第二列是修改日期。您会注意到组中的最后一个文件将始终具有最早的时间戳,这是我用来确定哪个文件是“原始”文件的标准。
以下是使用the获取所有重复项列表的命令
find ${PWD} -type f -exec stat -c %Y {} \; -exec md5sum '{}' \; | sed -r 'N;s/([0-9]+)\n([^ ]+) /\2 \1/g' | sort -r | uniq -w 32 --all-repeated=separate
答案 0 :(得分:1)
对行进行排序(使用sort
),将哈希值存储在临时变量中,并使用if
语句将其与当前值进行比较。另一个if
语句应该删除可能的空行。
例如:
| sort | awk '{ if ($0) { if (TEMP != $1) { print "Original: " $0 } else { print "Duplicate:" $0 } TEMP = $1 } }'
修改强>
由于您提供了这些说明,您可以这样做:
| tac | awk '{ if ($0) { if (TEMP != $1) { print "Original: " $0 } else { print "Duplicate:" $0 } TEMP = $1 } else { print "" } }' | tac
tac
反转了行顺序,实现了第一个示例中的排序。第二个tac
恢复原始订单。
答案 1 :(得分:1)
这个sed oneliner可能有效:
sed '$G' source | # append a newline to source
sed -nr '$!{N;s/^([^ ]+ )[^ ]+ +(.*\n)\1/Duplicate: \2\1/;s/^[^ ]+ [^ ]+ +(.*\n)$/Original: \1/;P;D}'
通过在源文件中附加换行符,问题就变成了两个替换,否定了任何EOF不优雅。
我猜一个sed解决方案是可以接受的,因为你在源文件准备中使用了sed。
答案 2 :(得分:0)
你怎么知道什么是重复的,什么是副本?这将是我的问题。
如果重复项在名称中都有Copy
,那将很容易,但是您的第一个示例,第一个重复项之一称为New Text Document.txt
,原始文件位于.svn
永远不应该看过的目录。
看起来你在第一列中有MD5哈希,这意味着你可以对它进行排序,然后使用awk
循环输出并在哈希值发生变化时打印一个空行。这会将你的文件组合在一起。
原始与副本将变得更加困难。你必须为此制定一个好的标准。您可以选择最早的修改日期(mdate
)。你也可以对此进行排序。当您打破哈希时,您可以简单地假设列表中的第一个文件(因为它具有最早的日期)是原始文件。
或者,您可以简单地假设文件名中嵌入了Copy
字样的那些是副本。然后,它可能并不那么重要。您是否希望程序仅识别重复项或删除它们?如果程序只是识别重复项,则无需确定哪些是原始文件,哪些是重复文件。你可以用你的眼睛比任何算法更好地做到这一点。
顺便说一下,这三列究竟是什么。我假设第一个是has,最后一个是文件名,但是中间的是什么?
答案 3 :(得分:0)
如果在每个组的最后一行之后出现空白行,包括最后一个组,并且文件名永远不会包含空格,那么这可能会有效。它取决于是否存在空白行。
awk 'NF == 3 { if (save != "") { printf("Duplicate: %s\n", save); } save = $3; }
NF == 0 { printf("Original: %s\n", save); save = ""; }'
如果缺少最后一个空行,则不会打印最后一行。
由于文件名中的空白(因此大多数行不只有3个字段),这不起作用。 Awk并不是最合适的工具。当Awk不适合时,我倾向于使用Perl:
#!/usr/bin/env perl
use strict;
use warnings;
my $save = "";
while (<>)
{
chomp;
if ($_ =~ m/^ (?:[\da-fA-F]+) \s+ (?:\d+) \s+ (\S.*)/x)
{
print "Duplicate: $save\n" if $save ne "";
$save = $1;
}
else
{
print "Original: $save\n\n";
$save = "";
}
}
这会产生:
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document.txt
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy.txt
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New Text Document - Copy (2).txt
Original: /home/evan/school_work/unix/Projects/Project2/finddups/.svn/tmp/tempfile.tmp
Duplicate: /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2 - Copy.txt
Original: /home/evan/school_work/unix/Projects/Project2/finddups/test/New folder/junk2.txt
如果你必须使用Awk,那么你需要在$0
时使用NF >= 3
,删除散列和inode号(或数据行上的第二个值)以找到文件名。
答案 4 :(得分:0)
awk '{
for (i = 0; ++i < NF;)
print "Duplicate:", $i
print "Original:", $NF
}' FS='\n' RS= infile