bash - как передать результат команды which на cd

87

Как я могу передать результат whichкоманды cd?

Вот что я пытаюсь сделать:

which oracle | cd
cd < which oracle

Но ни один из них не работает.

Есть ли способ добиться этого (вместо копирования / вставки, конечно)?

Изменить: если подумать, эта команда завершится ошибкой, потому что целевой файл НЕ является папкой / каталогом .

Итак, я думаю и разрабатываю лучший способ избавиться от конечной части "/ oracle" сейчас (sed или awk, или даже Perl) :)

Изменить: Хорошо, вот что у меня в итоге:

cd `which oracle | sed 's/\/oracle//g'`
Майкл Мао
источник
2
что дает вам команду, а не каталог
Anycorn
вы пытаетесь получить каталог, в котором установлена ​​программа? dirname, basename ?
Anycorn
@aaa: вы правы, я думаю, что dirname лучше, потому что оно указывает на "настоящий каталог", а не на символическую ссылку на исполняемый файл oracle ... вот почему мой sed apporach не сработает :)
Майкл Мао,

Ответы:

128

Вы используете конвейер в случаях, когда команда ожидает параметры из стандартного ввода. ( Подробнее об этом ).

В случае с cdкомандой дело обстоит иначе. Каталог - это аргумент команды. В таком случае можно использовать подстановку команд. Используйте обратные кавычки или, $(...)чтобы оценить команду, сохраните ее в переменной ..

path=`which oracle`
echo $path # just for debug
cd $path

хотя это можно сделать и гораздо проще:

cd `which oracle` 

или если на вашем пути есть специальные символы

cd "`which oracle`"

или

cd $(which oracle)

что эквивалентно обозначению обратных кавычек, но рекомендуется (обратные кавычки можно спутать с апострофами)

.. но похоже, что вы хотите:

cd $(dirname $(which oracle))

(который показывает, что вы можете легко использовать вложение)

$(...) (а также обратные кавычки) работают также в строках, заключенных в двойные кавычки, что помогает, когда результат может в конечном итоге содержать пробелы.

cd "$(dirname "$(which oracle)")"

(Обратите внимание, что для обоих выходов требуется набор двойных кавычек.)

михал
источник
Круто. Не могли бы вы немного объяснить, что здесь происходит? Это похоже на разыменование переменной; есть ли какая-то временная переменная по умолчанию, куда попадают результаты команды?
Nate W.
Аааа, я забыл о кавычках :(
Майкл Мао,
4
Вам нужно еще пару цитат: cd "$(dirname "$(which oracle)")".
Филипп
|Открывает новый процесс, так что даже если cdчитать из STDIN, cmd | cdне будет работать (т.е. текущий каталог в первоначальном процессе будет оставаться такой же).
Кайл Стрэнд
23

С dirname, чтобы получить каталог:

cd $(which oracle | xargs dirname)

EDIT: остерегайтесь путей, содержащих пробелы, см. Комментарий @anishpatel ниже


источник
2
Используйте, cd "$(which oracle | xargs -0 dirname)"если путь может содержать пробелы. Флаг -0 разделяет ввод на ноль, а не на пробел.
анишпател 04
9
cd `which oracle`

Обратите внимание, что это обратные кавычки (обычно клавиша слева от 1 на американской клавиатуре)

Cfreak
источник
1
Это не работает, если путь содержит пробелы или другие «специальные» символы, и вы должны удалить имя файла.
Филипп
@Philipp, вы можете использовать это, если на вашем пути есть специальные символыcd "`which oracle`"
Рам Патра
4

Хорошо, вот решение, использующее правильное цитирование:

cd "$(dirname "$(which oracle)")"

Избегайте обратных кавычек, они менее читабельны и всегда заключают в кавычки замены процесса.

Филипп
источник
2

Канал вам не нужен, вы можете делать все, что хотите, используя расширение параметров Bash!

Дополнительный совет: используйте «type -P» вместо внешней команды «which», если вы используете Bash.

# test
touch /ls
chmod +x /ls
cmd='ls'
PATH=/:$PATH
if cmdpath="$(type -P "$cmd")" && cmdpath="${cmdpath%/*}" ; then
   cd "${cmdpath:-/}" || { echo "Could not cd to: ${cmdpath:-/}"; exit 1; }
else
   echo "No such program in PATH search directories: ${cmd}"
   exit 1
fi
Башфу
источник
1

В ответ на ваш отредактированный вопрос вы можете удалить имя команды, используя dirname:

cd $(dirname `which oracle`)
Дэвид З
источник
Это не работает, если путь содержит пробелы или другие «специальные» символы.
Филипп
1
Легко исправить, заключив его в двойные кавычки.
David Z