我有一个包含十万多个ID的文件。每个ID由8~16位十六进制数字组成:
178540899f7b40a3
6c56068d
8c45235e9c
8440809982cc
6cb8fef5e5
7aefb0a014a448f
8c47b72e1f824b
ca4e88bec
...
我需要在包含周围的目录树中找到相关文件2×10 9文件。
给定一个像 的 ID 6c56068d219144dd
,我可以通过以下方式找到其相应的文件:
find /dir -type f -name '* 6[cC]56068[dD]219144[dD][dD] *'
但这至少需要两天才能完成......
我想做的是尽可能find
多地打电话给-o -iname GLOB
三胞胎ARG_MAX
。
这是我想做的事情:
sed -e 's/.*/-o -iname "* & *"' ids.txt |
xargs find /dir -type f -name .
我的问题是我不能强迫xargs
只接受完整的三胞胎。
我该怎么做?
答案1
这是错误的方法,如果重点是查找名称具有这些 ID 之一作为其空格分隔单词之一的所有文件,那么您可以这样做:
find /dir -type f -print0 |
gawk '
!ids_processed {ids[$0]; next}
{
n = split(tolower($NF), words, " ")
for (i = 1; i <= n; i++)
if (words[i] in ids) {
print
break
}
}' ids.txt ids_processed=1 RS='\0' FS=/ -
然后,您仅处理文件列表一次,查找 100k id 只是在哈希表中查找,而不是执行最多 100k 正则表达式/通配符匹配。
答案2
我会做什么:
编写一个脚本将所有文件名保存到临时文件中:
# maybe run this from cron or behind inotifywait
find dir -type f -print > /tmp/filelist
然后根据需要使用输入文件进行查找:
fgrep -if hexids /tmp/filelist
我可能建议使用-wif
代替,-if
但从其他评论来看,尚不清楚您在问题中提供了准确的信息。man grep
了解更多信息。
答案3
感谢@Kusalananda,我想到了一个可能的解决方案:
第一步是使 的每个-a -b X
三元组被视为单个参数xargs
。然后,您在内联脚本中重新拆分这些单参数三元组sh
并调用其中的实用程序。
... |
awk '{ printf("%s%c", $0, 0) }' |
xargs -0 sh -c '[ "$#" -gt 0 ] && { printf %s\\n "$@" | xargs "$0" }' my_command