我试图找出如何按名称过滤特定的 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 的输出。