如何使用bash执行任何命令"就地"编辑其文件(参数)?

jm.*_*jm. 109 sorting bash command-line

我有一个文件temp.txt,我想用sortbash中的命令排序.

我希望排序的结果替换原始文件.

这不起作用(我得到一个空文件):

sortx temp.txt > temp.txt
Run Code Online (Sandbox Code Playgroud)

这可以在一行中完成而无需复制到临时文件吗?


编辑:这个-o选项非常酷sort.我sort在我的问题中用作例子.我遇到了与其他命令相同的问题:

uniq temp.txt > temp.txt.
Run Code Online (Sandbox Code Playgroud)

有更好的通用解决方案吗?

dan*_*els 171

sort temp.txt -o temp.txt
Run Code Online (Sandbox Code Playgroud)

  • `for in in*txt; 做排序-o $ i $ i; done` (8认同)
  • 这是一个答案.我真的想知道是否有这个问题的通用解决方案.例如,如果我想在"就地"找到文件中的所有UNIQ行,我就不能做-o (3认同)

Bru*_*ine 29

A sort需要在开始输出之前查看所有输入.因此,sort程序可以轻松提供一个就地修改文件的选项:

sort temp.txt -o temp.txt
Run Code Online (Sandbox Code Playgroud)

具体来说,GNUsort文档说:

通常,sort在打开输出文件之前读取所有输入,因此您可以使用sort -o F F和等命令安全地对文件进行排序cat F | sort -o F.但是,sortwith --merge(-m)可以在读取所有输入之前打开输出文件,因此类似命令cat F | sort -m -o F - G不安全,因为sort Fcat读取之前可能会开始写入.

虽然BSD的文档sort说:

如果[the]输出文件是输入文件之一,则在排序并将输出写入[output]文件之前,将其复制到临时文件.

诸如的命令uniq可以在完成读取输入之前开始写入输出.这些命令通常不支持就地编辑(并且它们更难以支持此功能).

您通常使用临时文件解决此问题,或者如果您绝对想避免使用中间文件,则可以在写出之前使用缓冲区存储完整的结果.例如,用perl:

uniq temp.txt | perl -e 'undef $/; $_ = <>; open(OUT,">temp.txt"); print OUT;'
Run Code Online (Sandbox Code Playgroud)

这里,perl部分从uniq变量中读取完整输出$_,然后用这些数据覆盖原始文件.您可以使用您选择的脚本语言执行相同的操作,甚至可以使用Bash.但请注意,它需要足够的内存来存储整个文件,这在处理大文件时是不可取的.


小智 19

这是一种更通用的方法,适用于uniq,sort和whatnot.

{ rm file && uniq > file; } < file
Run Code Online (Sandbox Code Playgroud)

  • 另一种通用的方法,来自moreutils的`sponge`:`cat file | frobnicate | sponge file`. (14认同)
  • @Tobu:为什么不把它作为一个单独的答案提交? (3认同)
  • 有点危险 - 如果命令失败,您的数据就会丢失. (2认同)
  • @ patryk.beza:按顺序:输入FD从原始文件打开; 原始目录条目被删除; 处理重定向,创建一个新的空文件,其名称与以前的旧文件相同; 然后命令运行. (2认同)

Sea*_*ean 10

东武对海绵的评论保证本身就是一个答案.

引用moreutils主页:

到目前为止,moreutils中最常用的工具可能是sponge(1),它允许你做这样的事情:

% sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd
Run Code Online (Sandbox Code Playgroud)

但是,Steve Jessop在这里发表sponge了同样的问题.如果管道中的任何命令在sponge失败之前,则原始文件将被写入.

$ mistyped_command my-important-file | sponge my-important-file
mistyped-command: command not found
Run Code Online (Sandbox Code Playgroud)

哦,哦,my-important-file走了.


dav*_*avr 6

你去,一行:

sort temp.txt > temp.txt.sort && mv temp.txt.sort temp.txt
Run Code Online (Sandbox Code Playgroud)

从技术上讲,没有复制到临时文件,'mv'命令应该是即时的.

  • 嗯.我仍然会将temp.txt.sort称为临时文件. (6认同)
  • 此代码存在风险,因为如果排序因任何原因而未完成其作业而失败,则原始文件将被覆盖. (5认同)
  • 如果你想使用这样的东西使用&&(逻辑和)代替; 因为使用它将确保如果命令失败,则下一个命令将不会被执行.例如:cp backup.tar /root/backup.tar&& rm backup.tar如果你没有权利复制你将是安全的,因为文件不会被删除 (5认同)

joh*_*nyB 5

我喜欢这个sort file -o file答案,但不想两次输入相同的文件名。

使用 BASH历史扩展

$ sort file -o !#^
Run Code Online (Sandbox Code Playgroud)

当您按下 时,获取当前行的第一个参数enter

独特的就地排序:

$ sort -u -o file !#$
Run Code Online (Sandbox Code Playgroud)

获取当前行的最后一个参数。