使用命令的两行输出中的内容创建 2 个名称相似的文件

使用命令的两行输出中的内容创建 2 个名称相似的文件

我执行cmd并输出 2 行文本:

$ cmd
foo
bar

我需要将这些写入:`/long/path/x.{load,conf}

写入此目标需要超级用户权限,这排除了手动执行的操作:

$ echo "foo" > /long/path/x.load
$ echo "bar" > /long/path/x.conf

作为“重定向是在命令(sudo)启动并获取权限之前完成的”

鉴于foobar本身是笨重的文本字符串的占位符,那么实现此目的的好方法是什么?

我实际上正在寻找一种不会让人头疼的解决方案,因为这代表了一系列指令中的一个步骤,并且编写不言自明的代码会很好,但是我总是对所有可能的方法感兴趣做一点事。

答案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在写入输出文件之前会截断它们。如果你想追加,你可以只添加-apend 开关,并将tee输入数据复制到所有命名输出文件的尾部。

诚然,将每一行写入不同的位置有点困难。但sed提供w仪式命令。将其与其-expression 参数结合起来,您可以使用大括号扩展编写整个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"
}

相关内容