When you "pipe" input from one process or job to another, you are also spawning another process. Both of these jobs are said to be "children" of main process which called them (usually the process running the terminal emulator).
# 2 process are run here
# first job: echo
# second job: ls
echo "/home/" | ls
Looking at the source for zsh
, it looks like when the cwd
of a job differs from the original cwd
of the job after execution, it will notify the user with a message like (pwd now: foo)
. This helps to ensure that the user knows exactly where the are in the directory tree, which is especially useful when they may not have intended to do so. Below is taken from jobs.c where the cwd
(referred to as pwd
) where among other things, the cwd
(referenced as pwd
) are compared before printing the (pwd now: foo)
message. If they are different the message is printed, if they are equal it is not.
if ((lng & 4) || (interact && job == thisjob &&
jn->pwd && strcmp(jn->pwd, pwd))) {
doneprint = 1;
fprintf(fout, "(pwd %s: ", (lng & 4) ? "" : "now");
fprintdir(((lng & 4) && jn->pwd) ? jn->pwd : pwd, fout);
fprintf(fout, ")\n");
fflush(fout);
}
When you pipe something into ch
you are changing the cwd
in a child process and some of the normal checks which hide this message when calling cd
directly are bipassed. Otherwise cd
words in the same way.
# changes directories into ./test
echo "test" | cd
# (pwd now: /path/to/test)
# changes directory to home
echo | cd
# (pwd now: /home/<username>)
# calling this again will not echo the message, since the cwd is already
# the home directory and no change occurs
echo | cd
As for why the cwd
is changed to the home directory (~
) it is due to how cd
behaves when no paths are given as an argument. Unlike a lot of linux commands, cd
does not read from stdin
for paths to move into. Due to this, piping into cd
will simply populate stdin
for cd
, but that content is ignored. Because of this piping into cd
is the same as just calling cd
on its own.
# these next lines produce the same behavior
echo path/to/dir/test | cd
cd
When cd
does not receive a path to move to, it will move you to your home directory (referenced on linux systems as ~
)
# each of these lines produce the same behavior
cd /home/<username>
cd ~
cd