我有一个包含 14 个目录的目录结构,其中包含一堆包含三列格式数据的文件(用制表符分隔)。我打算使用 find 和 awk 从每个文件中提取第二列,并使用相同的文件名但在不同的根文件夹下输出它。这是我的目录的草图。
data/all -> AA, AB, AC, AD ...(A* 是包含以 3 列格式存储数据的文件的文件夹,例如 AA100.txt、AA101.txt ...)
我希望修改后的(一列)文件具有相同的名称,但都在一个新的根目录下 data/pos(而不是 data/all/)-> AA、AB、AC、AD ...(再次, 每个包含 A*100.txt, A*101...)
我的尝试是使用 find -exec 并为其提供 awk 命令,但是我在将文件输出到正确的位置时遇到了问题。
当在数据/全部/
find * -type f -exec awk '{print$2}' '{}' > ../pos/'{}' \;
但是 {} 作为输入文件的通配符在输出文件时似乎不起作用?
我究竟做错了什么?(顺便说一句,我在 ubuntu 服务器上)
我究竟做错了什么?
您正在使用重定向> ../pos/'{}'
,就好像它是由find
或处理的一样,awk
但重定向是由外壳处理的。在您的情况下,这意味着您只能重定向整个find
输出(而不是 的输出awk
)。
请注意,您通常不需要使用通配符*
作为find
. 常见的方式find .
是您想要做的还是有任何理由find *
?
find
与 Jacobo de Vera 的解决方案相比,这里我们将保持灵活性。awk
在 shell 循环中运行:
find . -type f -print0 |
while read -r -d $'\0' x; do
awk '{print $2}' "$x" > "../pos/$(basename "$x")"
done
Run Code Online (Sandbox Code Playgroud)
原来的方式-exec
效率较低,因为对于每个文件,除了启动一个 shell 之外,awk
多级转义在这里非常复杂:
find . -type f -exec sh -c 'awk "{print \$2}" "{}" > "../pos/{}"' \;
Run Code Online (Sandbox Code Playgroud)
也可能有一个替代解决方案在内部进行重定向awk
。
如果您想要的只是所有文件,您可以尝试不查找。在 中data/all/
,运行以下命令:
for file in ./*; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done
Run Code Online (Sandbox Code Playgroud)
如果您想覆盖 下整个层次结构中的文件/data/all
,则可以globstar
在使用 bash 时启用该选项(我相信这在 zsh 上“正常工作”),然后用于**
匹配所有文件:
shopt -s globstar
for file in ./**; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
19187 次 |
最近记录: |