Unix命令将文本添加到文件中

One*_*ree 108 unix command-line utilities prepend

是否有Unix命令将一些字符串数据添加到文本文件中?

就像是:

prepend "to be prepended" text.txt
Run Code Online (Sandbox Code Playgroud)

shi*_*ime 152

printf '%s\n%s\n' "to be prepended" "$(cat text.txt)" >text.txt
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案有问题...它将"\n"的出现转换为实际的新行...如果您在字符串包含"\n"的代码文件前面,则会出现问题. (31认同)
  • 这(1)将整个文件加载到内存中,(2)将整个文件粘贴到一个命令行参数中.很简单的东西,但要注意限制. (7认同)
  • 在一行和原始文本文件中!这是正确的简单答案.我建议额外的新行\n echo -e"要预先添加\n $(cat text.txt)"> text.txt (2认同)
  • 上次我尝试过,我相信这会在非常大的文件上中断,因为 cat 在被覆盖之前无法读取 text.txt 的全部内容。如果 echo 上的 -e 选项有问题,您可以在 bash 中引用换行符或执行 `echo "to be prepended"$'\n'"$(cat text.txt)"` (2认同)
  • @shime,你会接受修复错误的编辑吗?`printf '%s\n%s\n' "to be prepend" "$(cat text.txt)" >text.txt` 将避免 `echo -e` 的更不幸的副作用。(这仍然不是特别好的做法 - 取决于 shell 在重定向之前执行命令替换 - 但至少通过该修复,在一般情况下,对于以通常方式运行的 shell,它不会进行不需要的修改)。 (2认同)

Pri*_*ley 92

sed -i.old '1s;^;to be prepended;' inFile
Run Code Online (Sandbox Code Playgroud)
  • -i将更改写入到位,并在给出任何扩展名时进行备份.(在这种情况下,.old)
  • 1s;^;to be prepended;使用给定的替换字符串替换第一行的开头,使用;命令分隔符.

  • 如果你能用命令添加一些解释,那么对那些不太熟悉sed工作的人会有所帮助.OP可能希望在前置后插入`\n`; 取决于他们的需求.整洁的解决方案. (15认同)
  • 请注意,'\n'仅适用于GNU sed,而不适用于BSD(例如OSX,FreeBSD等).为了更方便,请参阅:/sf/ask/99503491/ (4认同)
  • @Levon我完全想插入`\ n`。应该先阅读评论。该死的。 (2认同)

Sri*_*bat 31

流程替代

我很惊讶没有人提到这一点.

cat <(echo "before") text.txt > newfile.txt
Run Code Online (Sandbox Code Playgroud)

这可以说比接受的答案更自然(打印一些东西并将其输入到替换命令中,这是字典上反直觉的).

...并且劫持了上面所说的ryan,sponge你不需要临时文件:

sudo apt-get install moreutils
<<(echo "to be prepended") < text.txt | sponge text.txt
Run Code Online (Sandbox Code Playgroud)

编辑:看起来这在Bourne Shell中不起作用 /bin/sh


这里是String

使用here-string - <<<(再次,你需要bash),你可以这样做:

<<< "to be prepended" < text.txt | sponge text.txt
Run Code Online (Sandbox Code Playgroud)

  • 这个答案对我来说是胜利者.仅使用内置版即可轻松实现.干得好! (3认同)
  • 问题是有 1 个文件,而不是 2 个文件。所以答案的第一行实际上不起作用。最后一行可能有效(但需要海绵)。 (2认同)

0xC*_*22L 27

这是一种可能性:

(echo "to be prepended"; cat text.txt) > newfile.txt
Run Code Online (Sandbox Code Playgroud)

你可能不会轻易绕过中间文件.

替代方案(shell逃逸可能很麻烦):

sed -i '0,/^/s//to be prepended/' text.txt
Run Code Online (Sandbox Code Playgroud)

  • 我认为策略 1) 是这里所有答案中最直观的。还有一个细微的变化: `cat &lt;(echo "to be prepend") text.txt &gt; newfile.txt `。想想看,我不确定我的是否相关,所以我发布一个单独的答案。 (3认同)

Ada*_*dam 16

这将有助于形成输出. - 表示标准输入,通过回声管道提供.

echo -e "to be prepended \n another line" | cat - text.txt
Run Code Online (Sandbox Code Playgroud)

要重写文件,需要临时文件,因为无法管道输入到输入文件中.

echo "to be prepended" | cat - text.txt > text.txt.tmp
mv text.txt.tmp text.txt
Run Code Online (Sandbox Code Playgroud)

  • 这不会根据请求将文本添加到文件`text.txt`,但会在stdout上显示.如果适用于OP,则输出可以汇集到不同的文件中 (2认同)

rya*_*yan 14

更喜欢亚当的回答

我们可以更容易地使用海绵.现在我们不需要创建临时文件并将其重命名

echo -e "to be prepended \n another line" | cat - text.txt | sponge text.txt
Run Code Online (Sandbox Code Playgroud)


Rob*_*b I 7

可能没有任何内置功能,但您可以轻松编写自己的内容,如下所示:

#!/bin/bash
echo -n "$1" > /tmp/tmpfile.$$
cat "$2" >> /tmp/tmpfile.$$
mv /tmp/tmpfile.$$ "$2"
Run Code Online (Sandbox Code Playgroud)

这样的东西至少......

  • 使用$$(当前PID)作为临时文件名的一部分+1.如果创建一般用途的脚本,这将阻止其他用户通过同时运行相同的脚本来覆盖临时文件. (6认同)
  • 但是,使用`$$`不足以生成代码(谷歌符号链接攻击); 但它肯定比静态文件名更好. (3认同)
  • 只需使用“mktemp” (2认同)

Mer*_*glu 7

另一种使用方式sed

sed -i.old '1 {i to be prepended
}' inFile
Run Code Online (Sandbox Code Playgroud)

如果要添加的行是多行:

sed -i.old '1 {i\ 
to be prepended\
multiline
}' inFile
Run Code Online (Sandbox Code Playgroud)


小智 7

在 Bash(在 Ubuntu 中)中测试,如果从一个测试文件开始,通过;

echo "Original Line" > test_file.txt

你可以执行;

echo "$(echo "New Line"; cat test_file.txt)" > test_file.txt

或者,如果 bash 的版本对于 $() 来说太旧了,你可以使用反引号;

echo "`echo "New Line"; cat test_file.txt`" > test_file.txt

并接收“test_file.txt”的以下内容;

New Line
Original Line
Run Code Online (Sandbox Code Playgroud)

没有中间文件,只有 bash/echo。

  • 最佳答案,我写了这个单行使用这个答案来旋转我的文件: for i in $(&lt;file2.txt); 做 echo "$(echo $i; cat file.txt)" &gt; file.txt; 完毕; (2认同)

mkl*_*nt0 6

如果替换输入文件是可以接受的:

注意:这样做可能会产生意外的副作用,特别是用常规文件替换符号链接,可能最终使用不同的文件权限,以及更改文件的创建(出生)日期.

sed -i,如约翰韦斯利亲王的回答,试图至少恢复原始权限,但其他限制适用.

 { printf 'line 1\nline 2\n'; cat text.txt; } > tmp.txt && mv tmp.txt text.txt
Run Code Online (Sandbox Code Playgroud)

注意:使用group命令{ ...; ... }比使用subshel​​l((...; ...))更有效.


如果输入文件应该就地编辑(保留其inode及其所有属性):

使用古老的edPOSIX实用程序:

注意:首先ed将输入文件作为整体读入内存.

ed -s text.txt <<'EOF' 
1i
line 1
line 2
.
w
EOF
Run Code Online (Sandbox Code Playgroud)
  • -s被压制ed的状态信息.
  • 注意命令如何ed作为多行here-document(<<'EOF' ... EOF)提供,即通过stdin.
  • 1i使1(第1行)成为当前行并开始插入模式(i).
  • 以下行是在当前行之前插入的文本,.以其自己的行终止.
  • w将结果写回到输入文件(用于测试,代替w,p打印的结果,而无需修改所述输入文件).


小智 6

在某些情况下,前置文本只能从stdin获得.那么这种组合应该有效.

echo "to be prepended" | cat - text.txt | tee text.txt
Run Code Online (Sandbox Code Playgroud)

如果要省略tee输出,则追加> /dev/null.

  • 是否保证`tee`在"cat"读取之前不会破坏`text.txt`?我认为不会 - 这会使这个解决方案对文件的健康造成危害. (4认同)
  • 用概念术语来说:**如果输入文件恰好大于系统的管道缓冲区大小**(现在通常为 64 KB),则此命令将导致数据丢失。 (3认同)
  • @JonathanLeffler可能没有.我试过这段代码来测试:`lenA = 1000000; 是的| head -c $ lenA> a.txt; LENB = 10000; b = $(是b | head -c $ lenB); echo"$ b"| 猫 - a.txt | tee a.txt>/dev/null`.如果`lenA`是1000000(1Mb文件)而`lenB`是10000(10Kb文本前置),则文件"a.txt"被20Kb的"b"字母覆盖.这完全被打破了.现在,如果你使用1Mb a.txt和1Mb文本进行前置,`tee`进入一个生成7Gb +文件的循环,我不得不停止命令.因此,很明显,对于大尺寸,结果是不可预测的.我没有关于它是否适用于小尺寸的信息. (2认同)

Vas*_*kov 6

解:

printf '%s\n%s' 'text to prepend' "$(cat file.txt)" > file.txt
Run Code Online (Sandbox Code Playgroud)

请注意,这对所有类型的输入都是安全的,因为没有扩展.例如,如果你想要前置!@#$%^&*()ugly text\n\t\n,它就会起作用:

printf '%s\n%s' '!@#$%^&*()ugly text\n\t\n' "$(cat file.txt)" > file.txt
Run Code Online (Sandbox Code Playgroud)

剩下要考虑的最后一部分是在命令替换期间在文件末尾删除空格"$(cat file.txt)".所有解决方法都相对复杂.如果要在file.txt结尾处保留换行符,请参阅:https://stackoverflow.com/a/22607352/1091436