views:

2915

answers:

10

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 soluiton?

A: 

Read up on the non-interactive editor, 'ex'

slim
+4  A: 

Here you go, one line:

sort temp.txt > temp.txt.sort && mv temp.txt.sort temp.txt

Technically there's no copying to a temporary file, and the 'mv' command should be instant.

davr
Hm. I'd still call temp.txt.sort a temporary file.
JesperE
But it's not making any unnecessary copies: it reads the input data once, and it writes the result once. So it may be a temporary file, but it's not copying to a temporary file (which is what he wanted to avoid)
davr
This code is risky, because if sort fails for whatever reason without completing its job, the original is overwritten.
Steve Jessop
Lack of disk space being a plausible cause, or a signal (user hits CTRL-C).
Steve Jessop
if you want to use something like this use
daniels
changed my answer to take your suggestions into account, thanks
davr
A: 

cat temp.txt | sort > temp.txt

duh... that does not work, I made a slight mistake when testing (I used >> instead of >) and jsut gave the impression that it worked.....

the -o option is the right answer.

webclimber
Nope. Tried that, didn't work. cat and sort will compete for writing to temp.txt.
JesperE
+12  A: 
sort temp.txt -o temp.txt
daniels
This is an answer. I was actually wondering if there is a generic solution to this problem. For example if I want to find all UNIQ lines in a file "in place", I can't do -o
jm
It's not generic, but you can use -u with GNU sort to find unique lines
James
+1  A: 

Use the argument --output= or -o

Just tried on FreeBSD: sort temp.txt -otemp.txt

sammyo
A: 

If you insist on using the "sort" program, you have to use a intermediate file -- I don't think "sort" has an option for sorting in memory. Any other trick with stdin/stdout will fail unless you can guarantee that the buffer size for sort's stdin is big enough to fit the entire file.

Edit: shame on me. "sort temp.txt -o temp.txt" works excellent.

JesperE
I read the Q also as being "in-place" but the second read made me believe he wasn't really asking for it
epatel
A: 

Many have mentioned the -o option. Here is the man page part.

From the man page:

   -o output-file
          Write output to output-file instead of to the  standard  output.
          If  output-file  is  one of the input files, sort copies it to a
          temporary file before sorting and writing the output to  output-
          file.
epatel
+3  A: 

A sort needs to see all input before it can start to output. For this reason, the sort program can easily offer an option to modify a file in-place:

sort temp.txt -o temp.txt

Specifically, the documentation of GNU sort says:

Normally, sort reads all input before opening output-file, so you can safely sort a file in place by using commands like sort -o F F and cat F | sort -o F. However, sort with --merge (-m) can open the output file before reading all input, so a command like cat F | sort -m -o F - G is not safe as sort might start writing F before cat is done reading it.

While the documentation of BSD sort says:

If [the] output-file is one of the input files, sort copies it to a temporary file before sorting and writing the output to [the] output-file.

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:

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

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.

Bruno De Fraine
+1  A: 

This would be highly memory constrained, but you could use awk to store the intermediate data in memory, and then write it back out.

uniq temp.txt | awk '{line[i++] = $0}END{for(j=0;j<i;j++){print line[j]}}' > temp.txt
JayG
+1  A: 

To add the uniq capability, what are the downsides to: sort inputfile | uniq | sort -o inputfile

jasper