10

I would like to take the output of a which command, and cd to the parent directory. For example, say I have the following:

which someprogram

With output:

/home/me/somedirectory/someprogram

And I would like to cd to the directory that someprogram lives in:

cd /home/me/somedirectory

I'd like to accomplish this in one line. What is the most elegant, tricky, short way to do this?

well actually
  • 3,225
  • 5
  • 22
  • 11

2 Answers2

16

Use dirname:

cd "`dirname $(which program)`"
Chris Down
  • 125,559
  • 25
  • 270
  • 266
Kevin
  • 40,767
  • 10
    +1 but use $() instead of backticks: cd $(dirname $(which program)) – glenn jackman Dec 01 '11 at 21:49
  • 1
    @glennjackman It works fine with one pair of backticks (as shown in the answer, or the other way around with the $() on the outside and the backticks on the inside). It just wouldn't work with an inner pair of backticks nested inside a separate outer pair of backticks. – Eliah Kagan Dec 02 '11 at 03:53
  • 3
    @EliahKagan I think @glennjackman's point was not that backticks don't work, but that they should be gradually phased out in favor of $() due to the many advantages of $() over backticks. – jw013 Dec 26 '11 at 17:57
5

In bash, I recommend type -p over which. which is an external command and it's tricky at times. You can use sed to remove everything after the final /, or use the special-purpose dirname utility.

cd "$(dirname -- "$(type -p program)")"
cd "$(type -p program | sed 's:[^/]*$::')"

On the command line, if you know that the directory doesn't contain any special characters (whitespace or \[?*), you can omit the quotes. You can also use backquotes instead of one of the $(…) (nesting backquotes is difficult, not worth it here).

cd `dirname $(type -p program)`
cd $(dirname `type -p program`)
cd `type -p program | sed 's:[^/]*$::'`

In zsh, there's a more compact syntax.

cd ${$(whence -p program):h}
cd ${$(echo =program):h}
cd ${${_+=program}:h}

(Yes, that last one is cryptic. It uses the ${VAR+TEXT} syntax on the _ variable, with the value being =program which is equivalent to $(whence -p program).)