更新

更新

我试图找出如何按名称过滤特定的 csv 文件,然后将其第二行提取到单个 csv 文件中。我不确定查找文件然后使用 sed/awk 等命令通过管道传输以提取所需的行是否是一个好主意。

find -name "data.csv" | sed -n 2p > final.csv 

更新

在 bash 脚本中使用 for 循环会生成所需的输出,但会在一行中打印所有输出。

for OUTPUT in $(find -name "data.csv")
do

        sed -n 2p $OUTPUT

done

请帮助我提出您的建议。

答案1

如果您查看 的输出find -name "data.csv",您会发现它打印了名为 的文件的完整路径名data.csv。管道将其传递给sed,后者打印其输入的第二行。

所以你的意思是,“这是文件列表。给我列表中的第二个文件。”你真正想说的是“这是一个文件列表。对于每个文件,给我第二行。”为此,您想使用xargs.

最有可能的是,你需要

find -name "data.csv" -print0 | xargs -0 -n 1 sed -n 2p > final.csv

使用find -print0 | xargs -0:是一个好-print0主意find,使用 NUL 字符作为文件名之间的分隔符而不是换行符,并-0告诉我们xargs期待这一点。这可以防止带有空格、回车或其他奇怪字符的文件名弄乱您的管道。

-n 1告诉它为找到的每个“data.csv”文件xargs运行单独的sed进程,而不是尝试将它们批处理在一起,这通常会使事情变得更高效。在这种情况下,如果您运行

sed -n 2p file1 file2 file3

它会在内部将所有输入文件连接到一个输入流中,并打印该输入流的第二行。但是RTFM:可能有一种方法可以让我sed不这样做,但我错过了。

答案2

查找的结果是 sed 需要执行操作的文件名列表。因此,使用 xargs 在该列表上一一执行 sed。但因为文件名甚至可以包含空格和换行符,所以最好使用 find 的“-print0”选项,用 ascii 零分隔文件名。另外,当这些文件很大时,您可以通过在第 2 行之后停止来节省 cpu 热量。然后您会得到:

find -name "data.csv" -print0 | xargs -0 -n 1 sed -n -e 2p -e 2q > final.csv

答案3

您可以执行以下操作:

find -name "data.csv" | xargs -n 1 sed -n 2p >> final.csv

请注意,上面使用>>将 sed 的结果连接到 Final.csv 中,在新行上,而不是替换它们,而>只是将 Final.csv 中的内容替换为 sed 的输出。

相关内容