Why does `cd` have no effect if output is piped?

Clash Royale CLAN TAG#URR8PPP
up vote
3
down vote
favorite
I accidentally typed
cd /tmp | tail
which is of course not what I meant. But to my surprise, I then did not change directory. Why is this? For comparison
cd /tmp > /tmp/foo
does result in a change of directory, so it's not the output redirection per sé. What's going on here?
pipe cd-command
add a comment |Â
up vote
3
down vote
favorite
I accidentally typed
cd /tmp | tail
which is of course not what I meant. But to my surprise, I then did not change directory. Why is this? For comparison
cd /tmp > /tmp/foo
does result in a change of directory, so it's not the output redirection per sé. What's going on here?
pipe cd-command
The pipe spawns a subshell that exits when tail exits. I would have expected only tail to be in the subshell, but I guess the cd is as well.
â jordanm
Jun 22 at 16:21
1
Butcd /tmp | pwdexhibits the same behavior --pwdshows an unchanged working directory.
â DopeGhoti
Jun 22 at 16:23
Each part of the pipeline is a separate process (maybe except last command).
â ctrl-alt-delor
Jun 22 at 16:56
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I accidentally typed
cd /tmp | tail
which is of course not what I meant. But to my surprise, I then did not change directory. Why is this? For comparison
cd /tmp > /tmp/foo
does result in a change of directory, so it's not the output redirection per sé. What's going on here?
pipe cd-command
I accidentally typed
cd /tmp | tail
which is of course not what I meant. But to my surprise, I then did not change directory. Why is this? For comparison
cd /tmp > /tmp/foo
does result in a change of directory, so it's not the output redirection per sé. What's going on here?
pipe cd-command
asked Jun 22 at 16:19
gerrit
1,11741326
1,11741326
The pipe spawns a subshell that exits when tail exits. I would have expected only tail to be in the subshell, but I guess the cd is as well.
â jordanm
Jun 22 at 16:21
1
Butcd /tmp | pwdexhibits the same behavior --pwdshows an unchanged working directory.
â DopeGhoti
Jun 22 at 16:23
Each part of the pipeline is a separate process (maybe except last command).
â ctrl-alt-delor
Jun 22 at 16:56
add a comment |Â
The pipe spawns a subshell that exits when tail exits. I would have expected only tail to be in the subshell, but I guess the cd is as well.
â jordanm
Jun 22 at 16:21
1
Butcd /tmp | pwdexhibits the same behavior --pwdshows an unchanged working directory.
â DopeGhoti
Jun 22 at 16:23
Each part of the pipeline is a separate process (maybe except last command).
â ctrl-alt-delor
Jun 22 at 16:56
The pipe spawns a subshell that exits when tail exits. I would have expected only tail to be in the subshell, but I guess the cd is as well.
â jordanm
Jun 22 at 16:21
The pipe spawns a subshell that exits when tail exits. I would have expected only tail to be in the subshell, but I guess the cd is as well.
â jordanm
Jun 22 at 16:21
1
1
But
cd /tmp | pwd exhibits the same behavior -- pwd shows an unchanged working directory.â DopeGhoti
Jun 22 at 16:23
But
cd /tmp | pwd exhibits the same behavior -- pwd shows an unchanged working directory.â DopeGhoti
Jun 22 at 16:23
Each part of the pipeline is a separate process (maybe except last command).
â ctrl-alt-delor
Jun 22 at 16:56
Each part of the pipeline is a separate process (maybe except last command).
â ctrl-alt-delor
Jun 22 at 16:56
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
3
down vote
accepted
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...
I understand whytailwould need to be in a subshell, but I don't understand by thecdmust be in a subshell, for the pipe to work.
â gerrit
Jun 22 at 23:17
having the parent process also run at various random points throughout the pipeline and handling I/O and deadlocks correctly would be much more complicated than simply forking off N children with the I/O wired up correctly
â thrig
Jun 23 at 14:33
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
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...
I understand whytailwould need to be in a subshell, but I don't understand by thecdmust be in a subshell, for the pipe to work.
â gerrit
Jun 22 at 23:17
having the parent process also run at various random points throughout the pipeline and handling I/O and deadlocks correctly would be much more complicated than simply forking off N children with the I/O wired up correctly
â thrig
Jun 23 at 14:33
add a comment |Â
up vote
3
down vote
accepted
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...
I understand whytailwould need to be in a subshell, but I don't understand by thecdmust be in a subshell, for the pipe to work.
â gerrit
Jun 22 at 23:17
having the parent process also run at various random points throughout the pipeline and handling I/O and deadlocks correctly would be much more complicated than simply forking off N children with the I/O wired up correctly
â thrig
Jun 23 at 14:33
add a comment |Â
up vote
3
down vote
accepted
up vote
3
down vote
accepted
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...
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...
answered Jun 22 at 16:43
thrig
21.8k12751
21.8k12751
I understand whytailwould need to be in a subshell, but I don't understand by thecdmust be in a subshell, for the pipe to work.
â gerrit
Jun 22 at 23:17
having the parent process also run at various random points throughout the pipeline and handling I/O and deadlocks correctly would be much more complicated than simply forking off N children with the I/O wired up correctly
â thrig
Jun 23 at 14:33
add a comment |Â
I understand whytailwould need to be in a subshell, but I don't understand by thecdmust be in a subshell, for the pipe to work.
â gerrit
Jun 22 at 23:17
having the parent process also run at various random points throughout the pipeline and handling I/O and deadlocks correctly would be much more complicated than simply forking off N children with the I/O wired up correctly
â thrig
Jun 23 at 14:33
I understand why
tail would need to be in a subshell, but I don't understand by the cd must be in a subshell, for the pipe to work.â gerrit
Jun 22 at 23:17
I understand why
tail would need to be in a subshell, but I don't understand by the cd must be in a subshell, for the pipe to work.â gerrit
Jun 22 at 23:17
having the parent process also run at various random points throughout the pipeline and handling I/O and deadlocks correctly would be much more complicated than simply forking off N children with the I/O wired up correctly
â thrig
Jun 23 at 14:33
having the parent process also run at various random points throughout the pipeline and handling I/O and deadlocks correctly would be much more complicated than simply forking off N children with the I/O wired up correctly
â thrig
Jun 23 at 14:33
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f451341%2fwhy-does-cd-have-no-effect-if-output-is-piped%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
The pipe spawns a subshell that exits when tail exits. I would have expected only tail to be in the subshell, but I guess the cd is as well.
â jordanm
Jun 22 at 16:21
1
But
cd /tmp | pwdexhibits the same behavior --pwdshows an unchanged working directory.â DopeGhoti
Jun 22 at 16:23
Each part of the pipeline is a separate process (maybe except last command).
â ctrl-alt-delor
Jun 22 at 16:56