I propose removing the caret (^) as a redirector for stderr in fish 3.0.
Reason 1: This is surprising for users of other shells and may lead to data loss
There are many commands using the caret on the command line for special purposes, e.g. git (see #1873). While some special handling has been introduced to reduce the need for quoting (see Reason 2), this does not help in all cases, e.g. git log ^refA refB will create a file refA containing the error message of git.
Many other programs use ^, too, for me the most notable problem is grep.
I often use the command dpkg -l|grep -v ^ii to check for problems with not fully installed or purged Debian packages. In fish this prints nothing, and grep's error message is sent to the new file ii.
Or I use ps auxww|grep ^theuser to quickly find processes of some users.
Or grep ^http someconfigfile to see if the config file contains a setting about httpserver or httpproxy or ...
While this often just results in a stray file (which is already bad enough), this can easily overwrite existing files, because sometimes I am looking for something where a file of the same name exists, e.g. Makefile targets (which luckily can often be rebuilt), or filtered output of ls, e.g. ls | grep -v ^README to show me everything but README (which is now overwritten) and various README.foo files. Or ls | grep -v ^access.log | grep -v ^error.log to hide the current and rotated web server log files and see what other files are present. Yes, I could add quotes and I should add a backslash in front of the dot in the regexp, but I really don't expect a file accessblog here, so I don't do it in interactive use.
Reason 2: Workarounds have been introduced, but they introduce even more surprising behavior.
To workaround the problem in git (#1873), the handling of ^ was changed to be different than the handling of >, so echo foo^bar prints foo^bar, but echo foo ^ bar prints foo and creates an empty file bar. This is different from e.g. echo foo>bar and echo foo > bar which both do the same thing.
The need for this workaround indicates that using the caret as a redirection character is problematic.
Reason 3: The law of orthogonality (https://fishshell.com/docs/current/design.html#ortho)
^ is just a shortcut for 2>, so this syntax saves only a single character.
The user still has to know the difference between stdout and stderr to use this feature.
The user still has to know about file descriptors to redirect both, stdout and stderr, to the same file with echo Hello > all_output.txt ^&1.
I propose removing the caret (^) as a redirector for stderr in fish 3.0.
Reason 1: This is surprising for users of other shells and may lead to data loss
There are many commands using the caret on the command line for special purposes, e.g. git (see #1873). While some special handling has been introduced to reduce the need for quoting (see Reason 2), this does not help in all cases, e.g.
git log ^refA refBwill create a filerefAcontaining the error message of git.Many other programs use ^, too, for me the most notable problem is grep.
I often use the command
dpkg -l|grep -v ^iito check for problems with not fully installed or purged Debian packages. In fish this prints nothing, and grep's error message is sent to the new fileii.Or I use
ps auxww|grep ^theuserto quickly find processes of some users.Or
grep ^http someconfigfileto see if the config file contains a setting about httpserver or httpproxy or ...While this often just results in a stray file (which is already bad enough), this can easily overwrite existing files, because sometimes I am looking for something where a file of the same name exists, e.g. Makefile targets (which luckily can often be rebuilt), or filtered output of
ls, e.g.ls | grep -v ^READMEto show me everything but README (which is now overwritten) and various README.foo files. Orls | grep -v ^access.log | grep -v ^error.logto hide the current and rotated web server log files and see what other files are present. Yes, I could add quotes and I should add a backslash in front of the dot in the regexp, but I really don't expect a fileaccessbloghere, so I don't do it in interactive use.Reason 2: Workarounds have been introduced, but they introduce even more surprising behavior.
To workaround the problem in git (#1873), the handling of ^ was changed to be different than the handling of >, so
echo foo^barprintsfoo^bar, butecho foo ^ barprintsfooand creates an empty filebar. This is different from e.g.echo foo>barandecho foo > barwhich both do the same thing.The need for this workaround indicates that using the caret as a redirection character is problematic.
Reason 3: The law of orthogonality (https://fishshell.com/docs/current/design.html#ortho)
^is just a shortcut for2>, so this syntax saves only a single character.The user still has to know the difference between stdout and stderr to use this feature.
The user still has to know about file descriptors to redirect both, stdout and stderr, to the same file with
echo Hello > all_output.txt ^&1.