Я пытаюсь cd
принять имя каталога, перенаправленное на него от другой команды. Ни один из этих методов не работает:
$ echo $HOME | cd
$ echo $HOME | xargs cd
Это работает:
$ cd $(echo $HOME)
Почему первый набор команд не работает, и есть другие, которые также терпят неудачу таким образом?
shell
io-redirection
pipe
cd-command
Jhonathan
источник
источник
Ответы:
cd
это не внешняя команда - это встроенная функция оболочки. Он запускается в контексте текущей оболочки, а не, как внешние команды, в контексте fork / exec'd как отдельный процесс.Ваш третий пример работает, потому что оболочка раскрывает переменную и подстановку команды перед вызовом
cd
встроенного, так чтоcd
получает значение в${HOME}
качестве аргумента.Системы POSIX делают имеют бинарный
cd
- на моей машине FreeBSD, это на/usr/bin/cd
, но он не делает то , что вы думаете. Вызов двоичного файлаcd
заставляет оболочку форкнуть / выполнить двоичный файл, который действительно меняет свой рабочий каталог на имя, которое вы передаете. Однако, как только он это делает, двоичный файл завершается, и разветвленный / exec'd процесс исчезает, возвращая вас к вашей оболочке, которая все еще находится в каталоге, в котором она находилась до вашего запуска.источник
cd
команды?cd
не читает стандартный ввод. Вот почему ваш первый пример не работает.xargs
необходимо имя команды, то есть имя независимого исполняемого файла.cd
должна быть встроенной командой оболочки и не иметь никакого эффекта (кроме проверки того, что вы можете перейти в этот каталог и возможные побочные эффекты, которые он может иметь, например, для автоматически монтируемых каталогов), если бы это был исполняемый файл. Вот почему ваш второй пример не работает.источник
В дополнение к существующему хорошему ответу также стоит упомянуть, что канал разветвляет новый процесс, который имеет свой отдельный рабочий каталог. Поэтому попытка сделать это не сработает:
Таким образом, вы не будете в папке / после того, как оболочка вернется из этой команды.
источник
a | b
, даже еслиa
иb
встроены, по крайней мере одна из них не запускается в процессе оболочки, но нет никакой гарантии, какой это будет. Например, в AT & Tksh
,zsh
илиbash -O lastpipe
,b
выполняется в текущем процессе оболочки, поэтому ваш код приведет вас туда / сюда.В дополнение к правильным ответам, которые уже даны: если вы запускаете bash и хотите узнать, что такое «команда», такая как cd, вы можете использовать type
или почему нет:
в то время как, например, время GNU обычно включено в ваш любимый дистрибутив:
Ладно, ладно, ты понял, тогда какого черта это тип?
Вот фрагмент руководства bash:
источник
Как уже говорили другие, это не сработает, потому что
cd
это встроенная команда оболочки, а не внешняя программа, поэтому у нее нет стандартного ввода, в который можно что-либо передать.Но, даже если бы это работало, это не сделало бы то, что вы хотите: канал запускает новый процесс и перенаправляет стандартный вывод первой команды на стандартный ввод второй, таким образом, только новый процесс изменит свою текущую работу каталог; это никак не могло повлиять на первый процесс.
источник
read
обычно (всегда?) встроенная оболочка. Это правда, чтоcd
игнорирует стандартный ввод, но это не потому, что он встроен.Другим вариантом являются обратные пометки, которые помещают стандартный вывод одной команды в качестве аргумента командной строки второй команды и являются более переносимыми, чем
$(...)
. Например:или в более общем смысле;
Обратите внимание, что использование обратных галочек зависит от оболочки для выполнения команды и замены вывода в командной строке. Большинство снарядов поддерживают это.
источник
$(...)
работает. Я не думаю, что это хороший совет, чтобы рекомендовать кавычки вместо этого, так как они имеют гораздо более запутанные правила цитирования и, как правило, более подвержены ошибкам. (См. §3.5.4 «Замена команд» в Справочном руководстве Bash .)$(...)
в одной системе, но не в другой?$(…)
. Системы без оболочки POSIX (то есть с подлинной оболочкой Bourne) были бы очень старыми. Даже системы, где/bin/sh
есть оболочка Bourne, и вам нужен другой путь, например,/usr/xpg4/bin/sh
чтобы получить оболочку POSIX, сегодня редки. Рекомендовать кавычки всем, кто профессионально не управляет древним Unix Boxen, оказывает им плохую услугу.