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,045
  • 5
  • 20
  • 11

2 Answers2

16

Use dirname:

cd "`dirname $(which program)`"
Chris Down
  • 122,090
  • 24
  • 265
  • 262
Kevin
  • 40,087
  • 16
  • 88
  • 112
  • 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](http://mywiki.wooledge.org/BashFAQ/082) 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).)

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175