Why doesn't "sort file1 > file1" work? Why doesn't "sort file1 > file1" work? unix unix

Why doesn't "sort file1 > file1" work?


As other people explained, the problem is that the I/O redirection is done before the sort command is executed, so the file is truncated before sort gets a chance to read it. If you think for a bit, the reason why is obvious - the shell handles the I/O redirection, and must do that before running the command.

The sort command has 'always' (since at least Version 7 UNIX) supported a -o option to make it safe to output to one of the input files:

sort -o file1 file1 file2 file3

The trick with tee depends on timing and luck (and probably a small data file). If you had a megabyte or larger file, I expect it would be clobbered, at least in part, by the tee command. That is, if the file is large enough, the tee command would open the file for output and truncate it before sort finished reading it.


It doesn't work because '>' redirection implies truncation, and to avoid keeping the whole output of sort in the memory before re-directing to the file, bash truncates and redirects output before running sort. Thus, contents of the file1 file will be truncated before sort will have a chance to read it.


It's unwise to depend on either of these command to work the way you expect.

The way to modify a file in place is to write the modified version to a new file, then rename the new file to the original name:

sort file1 > file1.tmp && mv file1.tmp file1

This avoids the problem of reading the file after it's been partially modified, which is likely to mess up the results. It also makes it possible to deal gracefully with errors; if the file is N bytes long, and you only have N/2 bytes of space available on the file system, you can detect the failure creating the temporary file and not do the rename.

Or you can rename the original file, then read it and write to a new file with the same name:

mv file1 file1.bak && sort file1.bak > file1

Some commands have options to modify files in place (for example, perl and sed both have -i options (note that the syntax of sed's -i option can vary). But these options work by creating temporary files; it's just done internally.