Why is `sort < "$f1" ` preferred over `sort -- "$f1"`, and why is this preferred over `sort "$f1"`?

sort "$f1"

fails for values of $f1 that start with - or here for the case of sort some that start with + (can have severe consequences for a file called -o/etc/passwd for instance).

sort -- "$f1"

(where -- signals the end of options) addresses most of those issues but still fails for the file called - (which sort interprets as meaning its stdin instead).

sort < "$f1"

Doesn't have those issues.

Here, it's the shell that opens the file. It also means that if the file can't be opened, you'll also get a potentially more useful error message (for instance, most shells will indicate the line number in the script), and the error message will be consistent if you use redirections wherever possible to open files.

And in

sort < "$f1" > out

(contrary to sort -- "$f1" > out), if "$f1" can't be opened, out won't be created/truncated and sort not even run.

To clear some possible confusion (following comments below), that does not prevent the command from mmap()ing the file or lseek()ing inside it (not that sort does either) provided the file itself is seekable. The only difference is that the file is opened earlier and on file descriptor 0 by the shell as opposed to later by the command possibly on a different file descriptor. The command can still seek/mmap that fd 0 as it pleases. That is not to be confused with cat file | cmd where this time cmd's stdin is a pipe that cannot be mmaped/seeked.


The issue is file names beginning with a dash. sort "$f1" doesn't work if the value of f1 starts with - because the command will interpret the value as an option. This usually results in an error but it could even cause a security hole. With sort -- "$f1", the double dash argument -- mean “no options beyond this point” so the value of f1 will not be interpreted as an option. But there is still one edge case: if the value of f1 is a dash and nothing else, then it isn't an option, it's the argument -, which means “standard input” (because the argument is an input file; for an output file it would mean “standard output”).

Using redirection avoids all of these pitfalls.

This applies to most commands, not just sort.