Pipes involve subshells, portions of which are not run in the parent shell and thus cannot affect the working directory of that parent shell process. This is how ZSH behaves:
% cd /tmp
% cd /var/tmp | tail
% pwd
/tmp
% echo foo | cd /var/tmp
(pwd now: /var/tmp)
% cd /tmp
% echo foo | cd /var/tmp | echo bar
bar
% pwd
/tmp
%
Note how the directory only changed when the cd
was the last command in the pipeline; this was run in the parent shell proper and thus was able to change the working directory of that process.
A useful use of this feature usually involves an explicit subshell and commands run therein:
dowork | ( cd elsewhere && domorework ) | andyetmore
also be sure to error check the cd
call instead of assuming it worked, unless you like rsync
output sprayed all over /
, or other such hypothetical messes...
cd /tmp | pwd
exhibits the same behavior --pwd
shows an unchanged working directory.