awk 命令读取文件路径位于另一个文件中的文件

MAZ*_*MAZ 2 bash awk

我有一个名为的文件path.txt,其中包含一些文件的目录路径作为行:

../../data/first.gz
../../data/second.gz
Run Code Online (Sandbox Code Playgroud)

我想读取path.txt,读取每一行,将这些文件(.gz 文件)的内容存储到一个新文件中。

我在这里发现了一个类似的问题awk 命令用于读取作为另一个文件和此代码内容的文件(文件名已更改以匹配我的数据)。

awk '{ while ((getline a < $0) > 0) print a }' path.txt >> newfile
Run Code Online (Sandbox Code Playgroud)

我是 awk 和 bash 的新手。我不知道如何修改上面的代码以使用 zcat 或类似的方式打开 zip 文件并将内容打印到 newfile。有人可以帮我修改代码或提出新的代码吗?提前致谢。

αғs*_*нιη 7

使用xargswith (这里假设其和选项zcat是 GNU 实现):-r-d

<path.txt xargs -rd'\n' zcat -- >>output
Run Code Online (Sandbox Code Playgroud)

要将zcat每个 .gz 文件输出到单独的输出文件中,您实际上根本不需要在此处使用 shell 循环,只需调用内联脚本,如下所示:

<infile xargs -rd'\n' -I{} sh -c 'zcat -- "$1" >output."${1##*/}"' xargs-sh {}
Run Code Online (Sandbox Code Playgroud)

  • 所有其他答案在循环中也同样有效,AMS。只需将“&gt;”替换为“&gt;&gt;”运算符即可。 (2认同)

ter*_*don 5

这里不需要awk,一个简单的 shell 循环就足够了:

while IFS= read -r gz; do
    zcat < "$gz"
done < path.txt >> newfile
Run Code Online (Sandbox Code Playgroud)

或者,将每个文件放入自己的文件中:

while IFS= read -r gz; do
    zcat < "$gz" > "${gz%.gz}.uncompressed" 
done < path.txt
Run Code Online (Sandbox Code Playgroud)

这里删除.gz后缀(如果有),并添加.uncompressed后缀以避免破坏名称不以.gz. 您还可以设置noclobber选项 ( set -o noclobber) 以避免破坏现有文件。

使用重定向而不是将文件名作为参数传递,可以避免zcat以 开头的文件名出现问题-,也可以避免在无法打开输入文件时创建输出文件。


Mar*_*ler 5

一个简单的方法,因为中的“cat”zcat代表“连接”,因此zcat需要一个文件列表来连接

\n
zcat -- $(cat path.txt) > newfile\n
Run Code Online (Sandbox Code Playgroud)\n

然而,这有点危险,因为 path.txt 可能包含带有空格 \xe2\x80\x93 的路径,并且你的 bash 会认为空格分隔参数。突然,../path/to/My document.txt.gz变成../path/to/Mydocument.txt.gz,而这两个都不存在!

\n
zcat -- $(cat path.txt) > newfile\n
Run Code Online (Sandbox Code Playgroud)\n

因为您只希望该设置应用于这一行,而不是 shell 会话的其余部分:

\n
IFS=$\'\\n\'; zcat -- $(cat path.txt) > newfile\n
Run Code Online (Sandbox Code Playgroud)\n

名为的文件*也将扩展到当前目录中的所有非隐藏文件名。

\n

因此,您想告诉 shell 它应该只关心换行符作为参数分隔符,并禁用通配符:

\n
( IFS=$\'\\n\'; zcat -- $(cat path.txt) > newfile )\n
Run Code Online (Sandbox Code Playgroud)\n

(顺便说一句,文件名也可以包含换行符,但我认为根据未处理的文件列表,这不是一个可以解决的问题)

\n

正如 St\xc3\xa9phane 指出的,除了zshbash还有更短的方法可以完成同样的事情:

\n
zcat -f -- ${(f)"$(<path.txt)"}\n
Run Code Online (Sandbox Code Playgroud)\n

因为zsh这是我的“家”shell,我很高兴了解到${(f)"somestring"}:它somestring在换行符处分裂;$(< path.txt)实际上与 相同$(cat path.txt),但不需要cat输出文件的内容 \xe2\x80\x93 该功能是 shell 的一部分。

\n

  • 在 `zsh` 中:`zcat -f -- ${(f)"$(&lt;path.txt)"}`。另请参阅 `bash` 中的 `readarray -t files &lt; path.txt &amp;&amp; zcat -f -- "${files[@]}"`。 (2认同)