0

The problem is that which is not storing the path to the program.

#!/bin/bash
read -p "Enter progam name: " name
path=which $name
nano $path
dimo414
  • 47,227
  • 18
  • 148
  • 244
  • i just like to look at them. –  Jul 18 '17 at 19:14
  • 2
    @janos `Which` works on any executable, not just binary. @MreeM, you can use `$()` around your `which $name` bit, like `path=$(which $name)` You should also quote your $path variable in case it has spaces: `nano "$path"` You could also just use `nano "$(which $name)"` – JNevill Jul 18 '17 at 19:16
  • @janos I've updated my comment/answer to remove the backtick suggestion. Hard to show an example of those within a codeblock here in a comment anywa. – JNevill Jul 18 '17 at 19:21
  • `which` will just look for files in `$PATH`, if the file you want to know the path is not in any directory set in your `$PATH`, `which` will not help you. You can use find to search for it, but search for it in you entire disk will take a long time, you should have at least some base path to search it. – Azize Jul 18 '17 at 19:34
  • `nano "$(which "$name")"`, rather, if you want to be able to refer to names with spaces. And better not to rely on `which`, which is nonstandard -- the POSIX-compliant alternative is `command -v`. – Charles Duffy Jul 18 '17 at 19:40
  • BTW, `path=which $name` is running `$name` as a command with the environment variable `path` set to the value `which`. It **does not** run `which`. – Charles Duffy Jul 18 '17 at 19:40

2 Answers2

2
path=which $name

This isn't the syntax you need. This invokes a command stored in $name with a variable path=which added to its environment. If you'd quoted it, as in path="which $name" you'd instead set path in your environment, but it would contain the string which ... (where ... is the value of $name).

What you're looking for is command substitution, which allows you to capture the output of a command. So instead you should do:

path="$(which "$name")"

This will set path to the result of which "$name", which is what you want.

As suggested in the comments you can skip the path variable entirely and just say:

nano "$(which "$name")"

You can even skip this script entirely assuming you don't mind remembering the syntax, and just entering:

$ nano "$(which command-to-look-at)"

Directly in the prompt.


Going the other way, if you want something more robust you can avoid opening binary files with something like this (notice it's a function rather than a script, you can add it to your .bashrc directly or pull out the body into a separate script if you prefer):

inspect_command() {
  local name="${1:?No command provided}"
  local path
  path=$(which "$name") || {
    echo "No command '$name' found"  
    return 1
  }
  if [[ "$(file --brief --mime-encoding "$path")" == "binary" ]]; then
    echo "$path appears to be a binary file."
    local response;
    read -p "Are you sure you'd like to continue? [y/N] " response;
    [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]] || return 0
  fi
  "${EDITOR:-nano}" "$path"
}

This behaves the same as above on text files (though you pass the command as an argument, and it uses your preferred EDITOR if one is set), but warns you before attempting to open binary files.

$ inspect_command curl
/usr/bin/curl appears to be a binary file.
Are you sure you'd like to continue? [y/N] n

$ inspect_command some_script.sh
... opens nano
dimo414
  • 47,227
  • 18
  • 148
  • 244
  • What is the meaning to run something like this: `nano "$(which curl)"`? It is a binary file. So I believe it is trying to open (edit with `nano`) a normal file, a text file, and a normal file probably will not be in the `PATH`. `which` can be used to get the path for a normal file also, but in this case it needs to update the `PATH` and this is exactly what is not know. – Azize Jul 18 '17 at 20:17
  • Right, it's not always a meaningful thing to do. There are many programs that *aren't* binaries, and which can be interesting to inspect. As OP noted above "*i just like to look at them*". – dimo414 Jul 18 '17 at 21:06
  • @Azize I've added an extended function that handles binary commands gracefully. There are many commands on the average `PATH` that are actually scripts; I bet you'll find more than you expect if you look. – dimo414 Jul 18 '17 at 21:39
-1

Use find instead of which.

path=$(find /some/base/path -type f -name "${name}")

Azize
  • 4,006
  • 2
  • 22
  • 38
  • 1
    The OP is explicitly asking only for the names of programs. Searching only through the PATH is appropriate, and much faster, in this case. – Charles Duffy Jul 18 '17 at 19:41
  • Please elaborate your explanation, it is clear for me what you are saying. – Azize Jul 18 '17 at 19:44
  • The OP's intent is to locate a program on the `PATH` (hence they're using `which`) and then open it. They can't use `find` since they aren't looking in a fixed `/some/base/path`. – dimo414 Jul 18 '17 at 19:49
  • But where in the question It says it is looking for files in PATH? – Azize Jul 18 '17 at 19:52
  • That's what `which` does - it looks for matching files on the `PATH`. – dimo414 Jul 18 '17 at 20:00
  • @Azize, that's the reasonable inference from the phrase "open a program", and the OP's attempt to use `which` (which would have worked if they got their syntax right). – Charles Duffy Jul 18 '17 at 20:05
  • I know that, but that is exactly the problem, let me quote the question: "The problem is that which is not storing the path to the program". It is not storing the path because usage of `which` is wrong, as stated before, or because the file is not in the PATH at all. – Azize Jul 18 '17 at 20:08