0

I have a short bash script cdline that takes two arguments PATHS and LINE and changes directory to the respective LINE in PATHS:

#!/bin/bash
#command for changing directory to that in the given line...
#or that of the file in the given line

PATHS=$1 LINE=$2 PATH="$(echo "${PATHS}" | sed -n ${LINE}p)" PATH="$(/home/gohomology/Scripts/pc_macros/file_system/getdir "${PATH}")" cd ${PATH}

return 1

This calls getdir which echoes the given path if its a directory, or the directory that includes the file otherwise.

I know that when calling a bash script normally it creates a subshell, so trying to call the script normally wouldn't do anything. As far as I understand, the solution for this should be sourcing the script, which one can do adding . or source before calling the script.

This indeed works for changing the directory, however, after doing so my terminal cannot find various commands such as ls or find, as demonstrated by the following result from my terminal emulator.

gohomology@gohomology:~/Desktop$ find . -name "example_file"
./example_dir/example_file

gohomology@gohomology:~/Desktop$ . cdline "$(!!)" 1 . cdline "$(find . -name "example_file")" 1

gohomology@gohomology:~/Desktop/example_dir$ ls Command 'ls' is available in the following places

  • /bin/ls
  • /usr/bin/ls

The command could not be located because '/usr/bin:/bin' is not included in the PATH environment variable. ls: command not found

gohomology@gohomology:~/Desktop/example_dir$ find . -name "example_file" Command 'find' is available in the following places

  • /bin/find
  • /usr/bin/find

The command could not be located because '/bin:/usr/bin' is not included in the PATH environment variable. find: command not found

The command cd still works after using cdline. I thought that the problem is that I'm stuck within a bash shell, which is why there's return 1 at the end of cdline, but the problem is still existent.

I run bash 5.1.16 and gnome-terminal on Ubuntu 22.04.2.

Cyrus
  • 12,309
  • Just declare -p PATH after every line in your script, and figure out where most of it gets clobbered. You really do not want to assign any intermediate values to PATH. Assign to newPath in your workings, and assign that to PATH as the last step. – Paul_Pedant Jul 02 '23 at 14:14
  • 2
    Use lowercase for your variables and you won't get these problems. – Cyrus Jul 02 '23 at 14:16
  • And quote all parameter expansions like "${1}", "${2}", "${PATH}". Most likely one of your original path directories has a space in it. – Paul_Pedant Jul 02 '23 at 14:19
  • Thanks! I changed the variable name from PATH to new_path, since I saw here that zsh might use path as a variable name, and for future-proofing. – gohomology Jul 02 '23 at 15:24
  • Also, why use return 1? Nonzero return codes are normally used to indicate errors. – Gordon Davisson Jul 02 '23 at 17:20

2 Answers2

1

The problem is that your script overrides your PATH environment variable:

PATH="$(echo "${PATHS}" | sed -n ${LINE}p)"
PATH="$(/home/gohomology/Scripts/pc_macros/file_system/getdir "${PATH}")"

If you look at the man pages of bash you'll see what this variable is used for:

PATH

The search path for commands. It is a colon-separated list of directories in which the shell looks for commands (see COMMAND EXECUTION below).

And then later under the Command Execution section:

If the name is neither a shell function nor a builtin, and contains no slashes, bash searches each element of the PATH for a directory containing an executable file by that name.

Since your PATH was overridden and now only includes your current working directory, bash doesn't know where to look for the command.

The error you see clearly states the problem:

The command could not be located because '/usr/bin:/bin' is not included in the PATH environment variable.

The reason your cd succeeded is that cd is not an executable file that bash runs, it is a bash builtin command.

Bottom line, don't use PATH for a variable name in the script, use a different name that's not used by bash.

aviro
  • 5,532
1

PATH is a special variable that tells the shell where to look for commands, don't use it as a temporary variable in your script.

from man bash.1

PATH

The search path for commands. It is a colon-separated list of directories in which the shell looks for commands (see COMMAND EXECUTION below). A zero-length (null) directory name in the value of PATH indicates the current directory. A null directory name may appear as two adjacent colons, or as an initial or trailing colon. The default path is system-dependent, and is set by the administrator who installs bash. A common value is ``/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin''.

memchr
  • 601