Closed marimlem closed 1 month ago
The command unset PATH | ls
does not work as expected because the unset
command and the ls
command are executed in separate subshells due to the use of the pipe (|
). The unset
command is executed in the first subshell, where it unsets the PATH
variable. However, this change does not affect the PATH
variable in the parent shell or any other subshells, including the one where ls
is executed.
The PATH
environment variable is crucial for the shell to locate executable files. When you unset PATH
, the shell loses the ability to find executables, including ls
, unless they are specified with their full path. However, since ls
is executed in a separate subshell, it does not inherit the modified PATH
from the first subshell where PATH
was unset.
To illustrate, if you run unset PATH | ls
, the unset PATH
command is executed in one subshell, and ls
is executed in another subshell. The ls
command in the second subshell does not know about the PATH
being unset in the first subshell, so it still has access to the PATH
variable as it was before the unset
command was executed.
If you want to unset PATH
and then run ls
, you would need to do it in the same subshell, like so:
unset PATH; ls
This command sequence unsets PATH
and then runs ls
in the same subshell, so ls
will not work as expected because PATH
is unset.
Citations: [1] https://askubuntu.com/questions/1023754/environment-path-variable-not-working-properly [2] https://unix.stackexchange.com/questions/167454/basic-commands-not-working-i-e-bash-ls-no-such-file-or-directory [3] https://stackoverflow.com/questions/32012645/bash-commands-dont-work-after-changing-path-variable [4] https://www.redhat.com/sysadmin/fix-command-not-found-error-linux [5] https://superuser.com/questions/1529159/why-i-cant-permanently-remove-these-environment-variables-into-an-ubuntu-18-04 [6] https://ubuntuforums.org/showthread.php?t=1442849 [7] https://serverfault.com/questions/885621/ls-command-doesnt-show-folder-but-i-cant-create-it-because-folder-already-exis [8] https://superuser.com/questions/1626116/bash-path-command-not-found [9] https://opensource.com/article/17/6/set-path-linux [10] https://www.digitalocean.com/community/tutorials/how-to-view-and-update-the-linux-path-environment-variable
When you run unset PATH
without using a pipe (|
), it is executed in the current shell environment, not in a subshell. This means that the PATH
variable is indeed unset for the duration of the current shell session, or until it is reset. The PATH
variable is crucial for the shell to locate executable files, so unsetting it will prevent the shell from finding any executables unless they are specified with their full path.
The behavior you observed with unset PATH | ls
is due to the use of the pipe, which creates a subshell for the command following the pipe. In this case, ls
is executed in a separate subshell, which inherits the environment from the parent shell, including the PATH
variable. Since PATH
was unset in the parent shell but not in the subshell where ls
is executed, ls
can still find its executable and run successfully.
In contrast, if you simply run unset PATH
without using a pipe, the PATH
variable is unset in the current shell environment, affecting the current shell session. This is why you might expect commands like ls
to fail after PATH
is unset, as they rely on PATH
to locate their executables. However, if you have a command like ls
that is built into the shell (as is the case with many shells), it might still work because the shell can execute built-in commands without relying on PATH
.
To summarize, unset PATH
without a pipe is executed in the current shell environment, affecting the current session. Using a pipe (|
) creates a subshell for the command following the pipe, which does not inherit the modified PATH
from the parent shell where PATH
was unset.
Citations: [1] https://stackoverflow.com/questions/370047/what-is-the-most-elegant-way-to-remove-a-path-from-the-path-variable-in-bash [2] https://unix.stackexchange.com/questions/446571/isolated-subshells-in-bash [3] https://askubuntu.com/questions/433329/how-to-remove-a-path-from-system-pathpath-using-terminal-commands [4] https://www.gnu.org/s/bash/manual/html_node/Command-Execution-Environment.html [5] https://www.reddit.com/r/bash/comments/1aw0o98/commands_executed_in_a_subshell_meaning/ [6] https://superuser.com/questions/271986/execute-a-command-from-another-directory-in-bash [7] https://stackoverflow.com/questions/55889522 [8] https://www.reddit.com/r/bash/comments/kbq6s5/i_accidentally_killed_my_path_and_now_all_of_the/ [9] https://discuss.circleci.com/t/unable-to-override-environment-variables-using-bash-env-and-ubuntu-machine-image/49422 [10] https://www.redhat.com/sysadmin/linux-environment-variables
this means, a simple unset PATH
command is not executed in a forked child process.
=> need to check for the command type before going into the execution loop.
=> which other commands do not invoke a child process? all builtins???
no subshell/fork in simple command without pipe:
unset VAR
export a=b
expected: ls doesn't work reality: ls works, and following commands also work.