我想做以下事情:
- 使用命令查找一组特定的文件
find
; - 对于任何找到的文件,将选项的相应输出
-printf
放入名为的变量中str
并将其传递给 Gawk(并且不要在其他任何地方打印/使用该输出); - 针对相应文件执行 Gawk 程序。相应变量的内容
str
必须在程序中可用。
例如,我有一个名为 的目录/d/ir
。它包含两个文件,file1.txt
和file2.txt
。这些文件采用 UTF-8 编码。名为 的文件file1.txt
包含以下两行文本:
A
BC
文件大小为4字节。
文件名为,file2.txt
包含以下三行文本:
D
EF
GHI
文件大小为8字节。
我想打印所有这些行,并在每行后面附加相应的内容str
(文件名、文件大小)。因此预期输出是
A;d/ir/file1.txt,4
BC;d/ir/file1.txt,4
D;d/ir/file2.txt,8
EF;d/ir/file2.txt,8
GHI;d/ir/file2.txt,8
我尝试了以下命令:
LC_ALL=en_US.utf8; find "/d/ir" -name "file*.txt" -type f -printf "%p,%s" -execdir gawk -v str="$7" '{
print($0 ";" str)
}' "{}" \+
(在这里我希望$7
,作为位置参数,将引用"%p,%s"
)但它不会打印预期的输出:它显示两个输出-printf
(我不希望发生这种情况),然后五行没有所需的数据str
。
正确的命令是什么?请注意,我不希望该-printf
选项的输出在 Gawk 上下文之外显示/打印:我只想将它们传递给 Gawk,这样只有 Gawk 程序知道如何使用它们。如果 Gawk 程序根本不使用它们,则它们不应该显示在任何地方。
由于该命令将用于许多文件,因此最大化性能和最小化内存消耗非常重要。
您的命令打印的内容
find
不会传递给gawk
。如果您想将某些内容传递给 ,gawk
请将 的输出通过管道传输find
到gawk
并让其gawk
处理,这可能会更好。您可以从标准输入中获取文件名及其大小,然后使用 读取每个文件的内容getline
进行打印。此解决方案还可以避免缓慢的 Shell 循环;这样就只有一个awk
。使用其他工具列出文件名
find
并处理它们的一个潜在问题是,文件名可以包含任何字符,包括空格和换行符,但 NUL 字符(以及/
文件基名)除外。当您使用
awk
支持 NUL 字符作为字段分隔符的 GNU 时,您可以为其提供以 NUL 分隔的find
输出,例如,文件名和大小的交替。这将解决文件名包含空格、换行符等所有可能的问题。如果您确实希望
gawk
每个文件单独显示一个大小,也可以从实用程序中获取大小stat
。示例中gawk
打印每个文件的第一行,然后是名称和大小。为了提高可读性,我们将gawk
脚本放在一个 Bash 函数中:变体为
execdir ... {} +
:使用任意 awk:
根据需要随意设置
LC_ALL
,不会影响逻辑。有关使用 的更多信息,请参阅http://awk.freeshell.org/AllAboutGetlinegetline
。我认为问题在于您尝试将
-printf
输出用作 gawk 的参数,但事实并非如此。您原来的方法行不通,因为它-printf
只是打印到标准输出,并没有设置任何 gawk 可以访问的变量。而且$7
在 gawk 中,它指的是每行输入的第 7 个字段,而不是 shell 变量。也许可以尝试一下这个:
我认为这个解决方案会将每个文件的元数据捕获到一个变量中,然后将其正确地传递给 gawk。这
\+
确保了文件被批量处理,从而获得了更好的性能。或者另一种方法是使用单独的 gawk 脚本文件或使用 heredoc 样式;
希望这对你有用。
stat
加载 filefuncs 后,你可以获取文件信息,包括其大小。例如将打印文件名,后跟当前工作目录中所有 txt 文件的大小(以字节为单位)。我不知道它与 相比有多快
find
,所以请自行测试并写下结果。(在 GNU Awk 5.3.1 中测试)