Unique sorting: Redirect output to the same file

You can use sponge from moreutils package:

LC_ALL=C sort -u filename | sponge filename

You also don't need pipe to uniq, since when sort has -u option to unique lines when sorting.

Note that on GNU system with UTF-8 locales, sort -u or sort | uniq didn't give you unique lines, but the first from sequence of lines which sort the same in current locale.

$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=en_US.utf8 sort | LC_ALL=en_US.utf8 uniq
①

gave you only . Changing locale to C force the sorting order based on the byte values:

$ export LC_ALL=C
$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=C sort | LC_ALL=C uniq
①
②

You don't need any extra command like cat and uniq and also without using rm command and mv command to removing and renaming the filename. just use simple command.

sort -u filename -o filename


 -u, --unique
        with -c, check for strict ordering; without -c, output only  the
        first of an equal run

 -o, --output=FILE
        write result to FILE instead of standard output

How it work?

sort command sorts your filename and with -u option, removes duplicate lines from it. then with -o option writes the output to the same file with in place method.


Your suggested example (below) doesn't work because you'd actually be reading from and writing to the same file simultaneously.

$ cat filename | sort | uniq > filename

The idea with a pipe or redirect is that the command on the left and right hand side of each pipe or redirect run simultaneously, in parallel. The command on the right processes information as it is handed over to it from the command on the left, while the command on the left is still running.

In order for your scenario to work, the command that reads from the file would need to finish before the command that writes to the file begins. In order for this to work you would need to redirect the output into a temporary location first, then once that's finished, send it from the temporary location back into the file.

A better way to do this is basically like in your former example, where you redirect to a temporary file then rename that file back to the original (except that you don't need to delete the file first, because moving deletes any existing target).

$ cat filename | sort | uniq > result
$ mv -f result filename

You could also save it into a string variable, except that only works when data is small enough to all fit in memory at once.