jxm*_*s12 5 shell-script text-processing files
我多次运行一个程序,输出(略微)不确定。每次,我都将输出打印到一个文件中。我现在有一个包含许多文本文件 (95,034) 的目录,其中可能有 4 个不同的独特输出。我很想看到这样的格式的输出:
A (50,000)
B (30,000)
C (10,000)
D (5,034)
Run Code Online (Sandbox Code Playgroud)
但即使只是看到 A、B、C、D(四种不同的可能输出)的内容也会很棒。我没有时间手动删除 90,000 个文件的重复数据。那么如何计算或列出目录中的唯一文本文件呢?谢谢!
小智 5
我是 GNU 的忠实粉丝datamash
(https://www.gnu.org/software/datamash/)。这是我创建并运行此命令的一组模拟文件的示例输出:
$ md5sum * | datamash -W -s -g 1 count 2 -f
5591dadf0051bee654ea41d962bc1af0 junk1 27
9c08c31b951a1a1e0c3a38effaca5863 junk2 17
f1e5cbfade7063a0c4fa5083fd36bf1a junk3 7
Run Code Online (Sandbox Code Playgroud)
有 27 个文件的哈希值为 5591...,其中之一是“junk1”。(与“junk2”相同的文件有 17 个,“junk3”有 7 个文件)。
该-W
说,使用空格作为字段分隔符。的-s -g 1
说,排序和由场1(它是散列)基团。在count
本来无论是现场1或2,无所谓。
在-f
写着“打印整个输入线”。这有一个怪癖,因为当您打印聚合结果时,它只打印它找到的每个组中第一行的整行。在这种情况下,效果很好,因为它为我们提供了每个 dup-set 中涉及的文件名之一,而不是所有文件名。
稍微扩展@Isaac 的解决方案......
假设bash
语法,并给出:
$ find test -type f
test/AA
test/A
test/C
test/CC
test/B
test/D
Run Code Online (Sandbox Code Playgroud)
其中文件 A 和 AA 相同,C 和 CC 也相同;
这是一个逐渐更有效的命令管道:
$ find test -maxdepth 1 -type f -exec bash -c "md5sum < {}" \; |
sort -k1,1 |
uniq --count
2 102f2ac1c3266e03728476a790bd9c11 -
1 4c33d7f68620b7b137c0ca3385cb6597 -
1 88178a003e2305475e754a7ec21d137d -
2 c7a739d5538cf472c8e87310922fc86c -
Run Code Online (Sandbox Code Playgroud)
现在剩下的问题是 md5 哈希值不会告诉您哪些文件是 A、B、C 或 D。这是可以解决的,尽管有点麻烦。
首先,将文件移至子目录中,或者如果更方便的话,将 PWD 移至上一个目录。在我的示例中,我正在工作.
并且文件位于test/
.
我建议您分别识别四种文件类型中的一种,并将它们复制到文件 A、B、C 和 D(如果需要,还可复制到文件 Z):
$ cp -p test/file1002 ./A
...
$ cp -p test/file93002 ./N
Run Code Online (Sandbox Code Playgroud)
等等。我们现在可以构建一个哈希表,定义每个唯一输出文件 AZ 的 md5 哈希值:
$ for file in [A-Z]; do
printf "s/%s/%s/\n" "$(md5sum < $file )" "$file";
done
s/102f2ac1c3266e03728476a790bd9c11 -/A/
s/4c33d7f68620b7b137c0ca3385cb6597 -/B/
s/c7a739d5538cf472c8e87310922fc86c -/C/
s/88178a003e2305475e754a7ec21d137d -/D/
Run Code Online (Sandbox Code Playgroud)
请注意,哈希表看起来像sed
语法。原因如下:
让我们运行find ... md5sum
上面相同的管道:
$ find test -maxdepth 1 -type f -exec bash -c "md5sum < {}" \; |
sort -k1,1 |
uniq --count
Run Code Online (Sandbox Code Playgroud)
...并将其通过一个sed
使用上面的哈希表的过程进行管道传输,以将哈希值替换为原型文件名。该sed
命令本身是:
sed -f <(
for file in [A-Z]; do
printf "s/%s/%s/\n" "$(md5sum < "$file")" "$file";
done
)
Run Code Online (Sandbox Code Playgroud)
因此,将它们连接在一起:
$ find test -maxdepth 1 -type f -exec bash -c "md5sum < {}" \; |
sort -k1,1 |
uniq --count |
sed -f <(
for file in [A-Z]; do
printf "s/%s/%s/\n" "$(md5sum < "$file")" "$file";
done
)
2 A
1 B
1 D
2 C
Run Code Online (Sandbox Code Playgroud)
如果您看到这样的输出:
2 A
1 B
1 5efa8621f70e1cad6aba9f8f4246b383 -
1 D
2 C
Run Code Online (Sandbox Code Playgroud)
这意味着某个文件的test/
MD5 值与您的文件 AD 不匹配。换句话说,E
某处存在一种输出文件格式。一旦找到它(md5sum test/* | grep 5efa8621f70e1cad6aba9f8f4246b383
),您可以将其复制到 E 并重新运行:
$ cp -p test/file09876 ./E
$ find test -maxdepth 1 -type f -exec bash -c "md5sum < {}" \; |
sort -k1,1 |
uniq --count |
sed -f <(
for file in [A-Z]; do
printf "s/%s/%s/\n" "$(md5sum < "$file")" "$file";
done
)
2 A
1 B
1 E
1 D
2 C
Run Code Online (Sandbox Code Playgroud)