8

I stumbled upon this behavior of zsh when using FreeBSD:

% dd if=/dev/zero bs=1M count=1 of=~/test2
dd: failed to open '~/test2': No such file or directory

This really confused me because the same thing works just fine in bash.

I can touch files using tilde in zsh, and then ls them:

% touch ~/test2
% ls ~/test2
/home/christoph/test2

At first, I assumed that zsh doesn't realize that there comes a path after of= so it didn't expand ~. But autocompleting file names works just fine. In fact, if use an existing file name, begin its path with ~, and then hit Tab at some point, the path gets expanded in the command I'm typing in.

Why does zsh pass ~/test2 to dd, not /home/christoph/test2?

zsh behaves the same on Linux. In fact, I executed these commands above and copied their outputs on a Linux machine.

11

~ is expanded only in a few contexts. POSIX, for the standard sh mandates echo a=~ to output a=~ (while it mandates ~ to be expanded in a=~ alone).

zsh however has a magicequalsubst option which you can use for ~ to be expanded after = even if it's not in assigments or arguments to the export/typeset... pseudo-keywords.

So:

$ echo a=~
a=~
$ set -o magicequalsubst
$ echo a=~
a=/home/chazelas

Note that bash, when not in POSIX/sh mode, expands ~ in word=~ but only when what's on the left of = looks like a literal unquoted bash variable name (regardless of whether it's in arguments to typeset/declare/export or any other command):

$ bash -c 'echo a=~'
a=/home/chazelas
$ bash -c 'echo "a"=~'
a=~
$ bash -c 'var=a; echo $var=~'
a=~
$ bash -c 'echo a.b=~'
a.b=~
$ (exec -a sh bash -c 'echo a=~')
a=~

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.