Shell one liner要预先添加到文件中

elm*_*rco 130 unix shell

这可能是一个复杂的解决方案.

我正在寻找像">>"这样的简单运算符,但是需要预先添加.

我担心它不存在.我必须做点什么

 mv myfile tmp
 cat myheader tmp > myfile

还有什么更聪明的吗?

Jas*_*ete 99

这仍然使用临时文件,但至少它在一行:

echo "text" | cat - yourfile > /tmp/out && mv /tmp/out yourfile
Run Code Online (Sandbox Code Playgroud)

Credit:BASH:将文本/行添加到文件中

  • 这意味着猫正在从管道中读取. (7认同)
  • 在`cat`之后做什么`-`? (4认同)
  • 警告:如果`yourfile`是一个符号链接,这将无法执行您想要的操作. (3认同)
  • @makboi “cat”后面的“-”是 Shell 编程中使用的约定,表示命令的输入应从“stdin”读取。答案中的命令(例如“echo”)的输出写入“stdout”,并使用管道“|”写入“cat”命令的“stdin”。将管道视为将一个命令的“stdout”传递到另一个命令的“stdin”,因此得名 - 左侧命令的输出流入右侧命令的输入 (3认同)

小智 31

echo '0a
your text here
.
w' | ed some_file
Run Code Online (Sandbox Code Playgroud)

ed是标准编辑器!http://www.gnu.org/fun/jokes/ed.msg.html

  • 或者,而不是硬编码要插入的文本:`0r header.file` (7认同)

Joh*_*Mee 29

下面的黑客是一个快速的袖手旁观的答案,工作和收到很多赞成票.然后,随着问题变得越来越流行,时间越来越长,愤怒的人们开始报告它有点工作,但奇怪的事情可能会发生,或者根本就没有用,所以它被激怒了一段时间.好好玩.

该解决方案利用了系统上文件描述符的精确实现,并且由于nixes之间的实现差别很大,因此它的成功完全取决于系统,绝对是不可移植的,并且不应该依赖于任何甚至非常重要的东西.

现在,尽管如此,答案是:


为文件创建另一个文件描述符(exec 3<> yourfile)从而写入那个(>&3)似乎克服了同一文件困境中的读/写.使用awk为600K文件工作.然而,使用'cat'尝试相同的技巧失败了.

将prependage作为变量传递给awk(-v TEXT="$text")克服了字面引号问题,该问题阻止了使用'sed'执行此操作.

#!/bin/bash
text="Hello world
What's up?"

exec 3<> yourfile && awk -v TEXT="$text" 'BEGIN {print TEXT}{print}' yourfile >&3
Run Code Online (Sandbox Code Playgroud)

  • 请谨慎使用!请参阅以下注释:http://stackoverflow.com/questions/54365/prepend-to-a-file-one-liner-shell/2754039#2754039 (4认同)
  • 警告:检查输出以确保没有任何更改,但第一行.我使用了这个解决方案,虽然它似乎有用,但我注意到似乎添加了一些新的线条.我不明白它们来自哪里,所以我不能确定这个解决方案真的有问题,但要注意. (3认同)
  • 如果它现在不可靠,那么如何用更好的解决方案更新答案呢? (3认同)

小智 20

John Mee:你的方法不能保证工作,并且如果你预先添加超过4096字节的东西可能会失败(至少gnu awk会发生这种情况,但我认为其他实现会有类似的约束).在这种情况下,它不仅会失败,而且会进入无限循环,它会读取自己的输出,从而使文件增长直到所有可用空间都被填满.

亲自尝试一下:

exec 3<>myfile && awk 'BEGIN{for(i=1;i<=1100;i++)print i}{print}' myfile >&3
Run Code Online (Sandbox Code Playgroud)

(警告:一段时间后杀掉它或者它会填满文件系统)

此外,以这种方式编辑文件是非常危险的,这是非常糟糕的建议,就好像在编辑文件时发生了某些事情(崩溃,磁盘已满),你几乎可以保证文件处于不一致的状态.

  • @Ikraav:也许吧,但是"评论"很长很精致(也很有用),看起来不太好,也许不适合StackOverflow的有限评论能力. (10认同)
  • 这应该是一个评论,而不是一个单独的答案. (6认同)

Vin*_*vic 18

没有临时文件是不可能的,但这里有一个oneliner

{ echo foo; cat oldfile; } > newfile && mv newfile oldfile
Run Code Online (Sandbox Code Playgroud)

您可以使用其他工具(如ed或perl)来执行此操作而无需临时文件.


ehd*_*hdr 16

值得注意的是,使用像mktemp这样的实用程序安全地生成临时文件通常是个好主意,至少如果脚本将以root权限执行.例如,您可以执行以下操作(再次使用bash):

(tmpfile=`mktemp` && { echo "prepended text" | cat - yourfile > $tmpfile && mv $tmpfile yourfile; } )
Run Code Online (Sandbox Code Playgroud)


小智 14

如果您在您控制的计算机上需要它,请安装包"moreutils"并使用"sponge".然后你可以这样做:

cat header myfile | sponge myfile
Run Code Online (Sandbox Code Playgroud)

  • 当与 @Vinko Vrsalovic 的答案结合使用时,这对我来说效果很好:`{ echo "prepending text"; 猫我的文件 } | 海绵我的文件` (2认同)

Eri*_*uff 12

使用bash heredoc可以避免使用tmp文件:

cat <<-EOF > myfile
  $(echo this is prepended)
  $(cat myfile)
EOF
Run Code Online (Sandbox Code Playgroud)

这是因为在执行重定向的cat之前,在评估bash脚本时评估$(cat myfile).


dbr*_*dbr 9

当你开始尝试在shell脚本中做一些困难的事情时,我强烈建议用"适当的"脚本语言(Python/Perl/Ruby/etc)重写脚本.

至于在文件前面添加一行,就不可能通过管道来实现,就像你做任何事情一样cat blah.txt | grep something > blah.txt,它无意中使文件空白.有一个叫做sponge可以安装的小实用程序命令(你这样做cat blah.txt | grep something | sponge blah.txt,它会缓冲文件的内容,然后将其写入文件).它类似于临时文件,但您不必明确地执行此操作.但我会说比Perl更糟糕的要求.

可能有一种方法可以通过awk或类似方法来实现,但是如果你必须使用shell脚本,我认为临时文件是迄今为止最容易(/唯一?)的方式.


cb0*_*cb0 9

假设您要编辑的文件是my.txt

$cat my.txt    
this is the regular file
Run Code Online (Sandbox Code Playgroud)

您想要添加的文件是标题

$ cat header
this is the header
Run Code Online (Sandbox Code Playgroud)

确保头文件中有最后一个空行.
现在你可以用它作为前缀

$cat header <(cat my.txt) > my.txt
Run Code Online (Sandbox Code Playgroud)

你结束了

$ cat my.txt
this is the header
this is the regular file
Run Code Online (Sandbox Code Playgroud)

据我所知,这只适用于'bash'.

  • `男人bash | 少'+ /过程替代' (5认同)

Dan*_*kov 7

编辑:这打破了.当使用cat和tee预先添加到文件时,请参阅奇怪的行为

覆盖问题的解决方法是使用tee:

cat header main | tee main > /dev/null
Run Code Online (Sandbox Code Playgroud)

  • 如果您发布的解决方案已损坏(并且实际上填满了用户的硬盘驱动器),请向社区寻求帮助并删除您的答案. (3认同)

Max*_*kov 7

就像Daniel Velkov建议的那样,使用tee.
对我来说,这是一个简单的智能解决方案:

{ echo foo; cat bar; } | tee bar > /dev/null
Run Code Online (Sandbox Code Playgroud)


小智 6

sed -i -e "1s/^/new first line\n/" old_file.txt
Run Code Online (Sandbox Code Playgroud)