如何在Bash中将文本添加到文件的开头?


285

嗨,我想在文件前添加文字。例如,我想将任务添加到todo.txt文件的开头。我知道,echo 'task goes here' >> todo.txt但这会将行添加到文件的末尾(不是我想要的)。


2
如果有没有有效的方式做到这一点对于大文件:unix.stackexchange.com/questions/87772/...
西罗桑蒂利新疆改造中心法轮功六四事件

@您可以看看这个方法superuser.com/a/1352628/11116
Evan Carroll

Answers:


374
echo 'task goes here' | cat - todo.txt > temp && mv temp todo.txt

要么

sed -i '1s/^/task goes here\n/' todo.txt

要么

sed -i '1itask goes here' todo.txt

4
第一个很棒!您介意解释逻辑吗?即时消息不是特别确定如何解释语法。
user479534 2011年

44
@ user8347:将使用(标准输入)作为第一个文件和第二个文件|的消息(echo '...')管道()。连接多个文件。将输出()发送到名为的文件。如果没有错误()从然后重命名()将文件恢复到原始文件()。cat-todo.txtcat>temp&&catmvtemptodo.txt
丹尼斯·威廉姆森

1
@itaifrenkel:我得看看你做了什么,但是如果cat收到字面反斜杠n,它将不会将其转换为换行符。其他必须做的。而不是cat,请尝试进行管道hexdump -C传递,以查看您是否实际在发送反斜杠和n或它是否是换行符。您也可以尝试cat -e显示行尾。
丹尼斯·威廉姆森

1
使用2和3(对我来说,3似乎更简单)使您可以一次在多个文件之前添加文本。
菲利克斯(Felix)2014年

4
@Kira:该1方法仅做文件上的一行的下一个命令和i命令插入。在手册页的“地址”部分和“零地址或单地址命令”部分中查找。
丹尼斯·威廉姆森

73

我认为一个更简单的选择是:

echo -e "task goes here\n$(cat todo.txt)" > todo.txt

之所以有效,$(...)是因为其中的命令是在执行之前todo.txt被覆盖的> todo.txt

虽然其他答案很好用,但我发现这很容易记住,因为我每天都使用echo和cat。

编辑:如果在中存在任何反斜杠,则此解决方案是一个非常糟糕的主意todo.txt,因为多亏了-e标志echo才能解释它们。将换行符添加到序言字符串中的另一种更容易的方法是...

echo "task goes here
$(cat todo.txt)" > todo.txt

...只需使用换行符。当然,它不再是单线的了,但实际上,以前也不是单线的。如果您要在脚本中执行此操作,并且担心缩进(例如,您要在函数内部执行缩进),则有一些变通办法可以使它仍然很合适,包括但不限于:

(echo 'task goes here' && cat todo.txt) > todo.txt
echo 'task goes here'$'\n'"$(cat todo.txt)" > todo.txt

另外,如果您担心是否在末尾添加了换行符todo.txt,请不要使用它们。好吧,倒数第二个除外。结局没有错。


1
我根本不执行$(...)。
SCL

2
这可能会更好地工作(或全部)配有双引号,而不是单一的...
ℝaphink

5
-e也不会在todo.txt中转换转义序列吗?
2013年

2
解决方法
yield-

printf的将是一个很大更加一致的跨平台和一般应工作比回声-e更顺畅
彼得·伯格

28

moreutils有一个很好的工具,叫做sponge

echo "task goes here" | cat - todo.txt | sponge todo.txt

它将“吸收” STDIN,然后写入文件,这意味着您不必担心临时文件和来回移动它们。

您可以moreutils通过Homebrew通过apt-get install moreutils或在OS X上获得许多Linux发行版,并带有。brew install moreutils


我会去(echo 'ble'; cat todo.txt):-)
Ciro Santilli新疆改造中心法轮功六四事件

11

您可以在Ex模式下使用Vim:

ex -s -c '1i|task goes here' -c x todo.txt
  1. 1 选择第一行

  2. i 插入

  3. x 保存并关闭


5

您可以创建一个新的临时文件。

echo "new task" > new_todo.txt
cat todo.txt >> new_todo.txt
rm todo.txt
mv new_todo.txt todo.txt

您也可以使用sedawk。但是基本上发生了同样的事情。


1
假设您的磁盘空间不足,因此new_todo.txt只能部分写入。您的解决方案似乎丢失了原始文件。
NPE

谁用完了磁盘空间?;-)这只是一个简单的例子。
基思

2
@Keith某人在VM上工作,但并不需要特别大的虚拟驱动器。或有人移动大文件。无论如何,反对这一点的真正理由是目录权限。如果您没有在给定目录中创建新文件的权限,则将在脚本中成功执行的唯一命令是rm原始文件的命令。
Parthian Shot

3

如果文本文件足够小以适合内存,则无需创建临时文件来替换它。您可以将它们全部加载到内存中,然后将其写回到文件中。

echo "$(echo 'task goes here' | cat - todo.txt)" > todo.txt

在不覆盖整个文件的情况下,不可能在文件的开头添加行。


只是问一个明显的问题:shell变量的字符数限制在哪里?
nixda 2013年

据我所知,它仅受可用内存量的限制。我已经将超过100MB的变量填入内存。text=$(cat file)。但是请务必仅使用文本,因为shell变量不是二进制干净的mywiki.wooledge.org/BashFAQ/058
Rucent88

2

您不能在文件开头插入内容。您唯一可以做的就是替换现有内容或在文件的当前结尾之后追加字节。

然后,对您的问题的任何解决方案都需要创建一个临时文件(或缓冲区)(在内存或磁盘上),该文件最终将覆盖原始文件。

当文件系统在此过程中碰巧已满时,请注意不要在创建新文件时保留原始文件而丢失数据。例如:

cat <(echo task go there) todo.txt > todo.txt.new && mv todo.txt.new todo.txt

欢迎下降投票者解释其动机。其余的答案,包括已接受的答案,都没有与我的答复相抵触。
jlliagre

这很难解析,因为<...>看起来像方括号,我认为它们不是。<和(之间的空格可能会有所帮助吗?
dumbledad

这对我不起作用。echo HOME=\"/g/Users/timregan/\" | cat - 'F:\Program Files\Git\etc\profile'可以,但是cat <echo HOME=\"/g/Users/timregan/\" 'F:\Program Files\Git\etc\profile'给出错误“ echo:没有这样的文件或目录”
dumbledad

@dumbledad您正在考虑我的答复。您没有任何内容可以解析。之间的空间<(将打破语法。试试cat <(echo HOME=\"/g/Users/timregan/\") 'F:\Program Files\Git\etc\profile'
jlliagre


0

GitBash + Windows10 + Multline

这是一个允许您使用多行字符串的版本

##############################################
## This section for demo purpose only,      ##
## So you can save entire file as           ##
## whatever.sh and run it.                  ##
##                                          ##
##############################################
> MY_TARGET_FILE.txt ##Make Or Clear File
echo "[STARTER_CONTENT]" >> MY_TARGET_FILE.txt
##############################################

## Below is main code:

##################################################
TARGET_FILE_VARIABLE="MY_TARGET_FILE.txt"
ADD_TO_HEAD_VARIABLE=$(cat << "HEREDOC_HEAD_TEXT"
//|  +-------------------------------------+   |//
//|  |                                     |   |//
//|  |     MESSAGE_FOR_HEAD_OF_FILE        |   |//
//|  |                                     |   |//
//|  +-------------------------------------+   |//
HEREDOC_HEAD_TEXT
)
##################################################
TAR=$TARGET_FILE_VARIABLE                       ##
TEX=$ADD_TO_HEAD_VARIABLE                       ##
echo "$TEX" | cat - $TAR > TEMP && mv TEMP $TAR ##
##################################################

## Expected contents of MY_TARGET_FILE.txt :
## //|  +-------------------------------------+   |//
## //|  |                                     |   |//
## //|  |     MESSAGE_FOR_HEAD_OF_FILE        |   |//
## //|  |                                     |   |//
## //|  +-------------------------------------+   |//
## [STARTER_CONTENT]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.