marimlem / minishell

0 stars 0 forks source link

unset PATH | ls #13

Closed marimlem closed 1 month ago

marimlem commented 4 months ago

expected: ls doesn't work reality: ls works, and following commands also work.

marimlem commented 4 months 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

marimlem commented 4 months ago

why does the sole command "unset PATH" then do it for the mainshell?

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

marimlem commented 4 months ago

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???

marimlem commented 4 months ago

no subshell/fork in simple command without pipe: unset VAR export a=b