我执行cmd
并输出 2 行文本:
$ cmd
foo
bar
我需要将这些写入:`/long/path/x.{load,conf}
写入此目标需要超级用户权限,这排除了手动执行的操作:
$ echo "foo" > /long/path/x.load
$ echo "bar" > /long/path/x.conf
作为“重定向是在命令(sudo)启动并获取权限之前完成的”
鉴于foo
和bar
本身是笨重的文本字符串的占位符,那么实现此目的的好方法是什么?
我实际上正在寻找一种不会让人头疼的解决方案,因为这代表了一系列指令中的一个步骤,并且编写不言自明的代码会很好,但是我总是对所有可能的方法感兴趣做一点事。
答案1
Awk 的重定向运算符在这里派上用场。以下是该主题的一些变体。
cmd | sudo awk '{print >"/long/path/x." (NR==1 ? "load" : "conf")}'
cmd | sudo x=/long/path/x awk 'NR==1 {print >ENVIRON["x"]".load"}
NR==2 {print >ENVIRON["x"]".conf"}'
cmd | sudo awk 'FNR==1 && NR!=1 {exit} {print >ARGV[NR-1]}' - /long/path/x.{load,conf}
第一个是最短的,也是最简单的。每行都打印到通过评估运算符后面的表达式确定的文件名>
。当前行号NR
用于计算文件名。表达式的并置就是awk中的字符串连接运算符。
答案2
人们通常这样做tee
:
cmd | sudo tee /long/path/x.{load,conf}
tee
将其输入的副本写入其所有命名输出文件 - 并且以同样的方式,重定向发生exec
在大括号扩展中的参数生成之前。因此,上面的代码应该可以正常工作,并立即写入结果文件名和标准输出。
如果您不想tee
在复制数据时看到终端上写入的内容,您可以将标准输出重定向到/dev/null
-sudo
不会干扰该重定向。
您应该注意,正如所写的那样,tee
在写入输出文件之前会截断它们。如果你想追加,你可以只添加-a
pend 开关,并将tee
输入数据复制到所有命名输出文件的尾部。
诚然,将每一行写入不同的位置有点困难。但sed
提供w
仪式命令。将其与其-e
xpression 参数结合起来,您可以使用大括号扩展编写整个sed
脚本:
cmd | sudo sed -e'$x;/./w '/long/path/x.{load,conf}$'\n1x'
...将w
第一行写入第一个参数文件,将第二行写入第二个参数文件。 e 的x
更改只是平衡第一行和第二行之间的脚本 - 以防止sed
将两行写入每行的两个文件中。
我测试它是这样的:
printf %s\\n 1 2 |
sed -e'$x;/./w '/tmp/{1,2}$'\n$!x'
……然后就跑了……
head /tmp/[12]
...打印...
==> /tmp/1 <==
1
==> /tmp/2 <==
2
答案3
我不确定您是否想要一个解决方案来编写整个事情的脚本(从命令cmd
到.load
文件.conf
设置,但根据设置这些文件,您仍然可以使用 sudo 来完成,但您确实需要重定向成为苏杜德命令:
$ sudo sh -c "echo 'foo' > /long/path/x.load"
$ sudo sh -c "echo 'bar' > /long/path/x.conf"
这里sudo
将获得更高的权限,然后运行sh
shell,它反过来会解释给定的命令,并且只有在那一刻才会发生重定向,避免任何权限问题。
如果您碰巧需要编写此脚本,则根据您的具体需求,它可能看起来像这样:
cmd | {
read line
sudo sh -c "echo '$line' > /long/path/x.load"
read line
sudo sh -c "echo '$line' > /long/path/x.conf"
}