tar 列出文件,在第一个文件处中断

tar 列出文件,在第一个文件处中断

我一直在使用从类似帖子中提取的以下片段 -https://unix.stackexchange.com/a/101273/212793- 从文件中获取文件名tar.gz

tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }'

就我而言,我只需要一个特定文件,因此我使用类似以下内容的文件:

tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' | grep -e "^..*my-file-name\\.ext$"

关键是,我的.tar.gz很大,包含很多文件。然而,每个都在开头附加了一个类似的“哈希”(因此是^..*我的 grep'd 正则表达式的一部分)。

所以这些文件可能看起来像:

- 4b77e4e1_file-a.ext
- 4b77e4e1_file-b.ext
- 4b77e4e1_file-c.ext
# ect.

tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }'我注意到获取所有文件 ( ) 流输出的命令。

我的想法是,如果我可以“破坏”流,然后提取第一个哈希部分,我就可以构建我最终需要的文件名,而不必循环遍历文件的整个内容.tar.gz

所以我的问题是,如何awk在其第一个输出上“中断”,而不是等待整个命令完成(这需要几分钟)并 grep 结果以获得我最终想要的文件名

编辑:看起来我实际上想中断tar,因为exit在第一个结果之后简单地 ing 不会改变执行时间。

答案1

尝试类似的东西

 tar tzf "archive.tar.gz" | awk -F/ '$NF ~ /my-filename$/ {print $NF ; exit }'

或者

 tar tzf "archive.tar.gz" | awk -F/ 'substr($NF,4,11) == "my-filename" {print $NF ; exit }'

(其中 4 和 11 与实际文件名匹配)。

答案2

如果管道中的程序之一退出,则其左侧的程序也将退出。它的工作方式是:

  • foo | barbar退出。
  • 退出进程会关闭管道的读取端。
  • foo尝试写入管道时,它会收到 SIGPIPE 信号。
  • foo死了。

这是假设foo没有针对 SIGPIPE 进行防护;程序可以做到这一点,但典型的命令行程序不能。

由于您只想要一场比赛,因此 awk 在找到您感兴趣的行后立即退出:

tar tzf "archive.tar.gz" | awk -F/ '$NF ~ /.my-file-name\.ext$/ {print $NF; exit}'

或者(这里并不是很有利)

tar tzf "archive.tar.gz" | sed -n '/[^/]my-file-name\.ext$/ {s!.*/!!; q}'

或者,坚持使用 grep 与 awk 分开的更复杂的方法

tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' | grep -e "^..*my-file-name\\.ext$" | head -n 1

从读取器退出会导致tar下次写入管道时退出,这可能需要一段时间,因为输出缓冲。 (如果管道上有两个以上的进程,则需要特别长的时间,因为每个进程接收 SIGPIPE 都会有一些延迟。)awk退出后,find将花费一点时间读取存档并用以下内容填充下一个缓冲区文件名,然后最后尝试写入缓冲区并被 SIGPIPE 杀死。对于此应用程序,将 tar 切换到行缓冲进行输出可能会更快,您可以使用stdbuf

stdbuf -oL tar tzf "archive.tar.gz" | awk -F/ '$NF ~ /.my-file-name\.ext$/ {print $NF; exit}'

或者,您可以安排在 awk 退出时终止 tar 程序,但这更复杂。

sh -m 'tar tzf "archive.tar.gz" | {
         awk -F/ "$0";
         kill -TERM -$$;
       }' '$NF ~ /.my-file-name\.ext$/ {print $NF; exit}'
[ $? -eq 143 ]

答案3

您可以告诉 AWK 在打印某些内容后退出:

awk -F/ '$NF != "" { print $NF; exit }'

由于您正在寻找特定的文件名:

awk -F/ '/my-file-name\.ext$/ && $NF != "" { print $NF; exit }'

那么测试$NF是多余的:

awk -F/ '/my-file-name\.ext$/ { print $NF; exit }'

相关内容