1

In writing the question:

How to touch and cat file named -

I was trying to generalise to a case where a file named - was stored in a variable.

In zsh, I tried setting a variable to contain a single hyphen:

% var=-
% echo $var

% var='-'
% echo $var

% var=\-
% echo $var

%

Why don't these work?

Why is zsh different to bash in this regard?

How do I set $var to -?

Tom Hale
  • 28,728
  • 32
  • 139
  • 229

1 Answers1

6

Again, as often, it's not the value actually in the variable, but how the variable is. The echo in this case. Zsh's echo takes the single dash as an end of options indicator, so it's removed. Online manual:

Note that for standards compliance a double dash does not terminate option processing; instead, it is printed directly. However, a single dash does terminate option processing, so the first dash, possibly following options, is not printed, but everything following it is printed as an argument. The single dash behaviour is different from other shells. For a more portable way of printing text, see printf, and for a more controllable way of printing text within zsh, see print.

So we have:

zsh% echo -

zsh% echo - -n
-n
zsh% var=-
zsh% printf "%s\n" "$var"
-

See also:

ilkkachu
  • 133,243
  • 15
  • 236
  • 397
  • So this needs to be seen as a bug in `zsh`. – schily Sep 08 '18 at 15:18
  • 1
    @schily, sure, go ahead and report is as such. – ilkkachu Sep 08 '18 at 15:24
  • See also: https://www.zsh.org/mla/workers/2018/msg00202.html – Stéphane Chazelas Sep 09 '18 at 18:40
  • @schily : I wouldn't see it as a bug. The behaviour is exactly as documented in the zsh man page. Note that if you don't like this behaviour of the `echo` builtin in Zsh, you can always use, i.e., `command echo $var` instead of `echo $var` and your dash will be printed. – user1934428 Sep 10 '18 at 08:46
  • @user1934428, using the system's `echo` will not necessarily help. For instance, on GNU systems, you'll still have problems for values of `$var` like `-n`, `--version`, `-Ene`... In `zsh`, `echo -E - $var`, `print -r -- $var` and `printf '%s\n' "$var"` should be equivalent but only the latter one is portable to other Bourne-like shells which is why zsh and POSIX recommend to use `printf` here. Only zsh and yash `echo`s are able to output arbitrary data. – Stéphane Chazelas Sep 10 '18 at 10:09
  • @StéphaneChazelas : Sorry to disagree in this point, but I tried it on Cygwin (which is, admittedly, not Linux, but at least the utilities are GNU based), and `/bin/echo -` outputs does output a dash. Right now, I also have access to some (somewhat older) Linux, and here too, it works. Could you cite a source which would explain why my approach wouldn't work? – user1934428 Sep 10 '18 at 16:02
  • @user1934428, yes, that `echo -` handling is specific to `zsh` (some old versions of pdksh output nothing on `echo -` but that was a bug then). I was pointing out that GNU `echo` (and most other `echo` implementations) have issues of their own, not on `-` but other values of `$var` like `--version`, `-nene`... So using another `echo` **in general** is not the best solution. – Stéphane Chazelas Sep 10 '18 at 16:07