I have a file temp.txt, that I want to sort with the sort
command in bash.
I want the sorted results to replace the original file.
This doesn't work for example (I get an empty file):
sortx temp.txt > temp.txt
Can this be done in one line without resorting to copying to temporary files?
EDIT: The -o
option is very cool for sort
. I used sort
in my question as an example. I run into the same problem with other commands:
uniq temp.txt > temp.txt.
Is there a better general solution?
Here you go, one line:
Technically there's no copying to a temporary file, and the 'mv' command should be instant.
This would be highly memory constrained, but you could use awk to store the intermediate data in memory, and then write it back out.
Here's a more general approach, works with uniq, sort and whatnot.
An alternative to
sponge
with the more commonsed
:It works for any command (
sort
,uniq
,tac
, ...) and uses the very well knownsed
's-i
option (edit files in-place).Warning: Try
command file
first because editing files in-place is not safe by nature.Explanation
Firstly, you're telling
sed
not to print the (original) lines (-n
option), and with the help of thesed
'sr
command andbash
's Process Substitution, the generated content by<(command file)
will be the output saved in place.Making things even easier
You can wrap this solution into a function:
Example
To add the
uniq
capability, what are the downsides to:A
sort
needs to see all input before it can start to output. For this reason, thesort
program can easily offer an option to modify a file in-place:Specifically, the documentation of GNU
sort
says:While the documentation of BSD
sort
says:Commands such as
uniq
can start writing output before they finish reading the input. These commands typically do not support in-place editing (and it would be harder for them to support this feature).You typically work around this with a temporary file, or if you absolutely want to avoid having an intermediate file, you could use a buffer to store the complete result before writing it out. For example, with
perl
:Here, the perl part reads the complete output from
uniq
in variable$_
and then overwrites the original file with this data. You could do the same in the scripting language of your choice, perhaps even in Bash. But note that it will need enough memory to store the entire file, this is not advisable when working with large files.