1つのコマンドから出力されたパス名を「cd」にリダイレクトできないのはなぜですか?


27

cd別のコマンドからリダイレクトされたディレクトリ名を受け入れようとしています。これらの方法はどちらも機能しません。

$ echo $HOME | cd
$ echo $HOME | xargs cd

これは動作します:

$ cd $(echo $HOME)

最初のコマンドセットが機能しないのはなぜですか?


他の人は、この方法で失敗するcdを使用する他のコマンドまたは他の方法を参照していますか?
ディディコーエン

@DavidKohen私は他のコマンドを参照
ジョナサン

いくつかの注目すべき例は、ulimit、umask、popd、pushd、set、export、readです。
ディディコーエン

回答:


32

cd外部コマンドではなく、シェルの組み込み関数です。現在のシェルのコンテキストで実行されますが、外部コマンドのように、fork / exec'dコンテキストでは別のプロセスとして実行されません。

3番目の例は、シェルがcd組み込み関数を呼び出す前に変数とコマンド置換を展開し、その引数としてcdの値を受け取るため、${HOME}機能します。

POSIXシステムにバイナリがありますcd-私のFreeBSDマシンでは、に/usr/bin/cdありますが、あなたが思っていることはしません。バイナリcdを呼び出すと、シェルはバイナリをfork / execします。これにより、実際に作業ディレクトリが渡した名前に変更されます。ただし、そうするとすぐにバイナリが終了し、fork / exec'dプロセスが消え、シェルに戻ります。シェルは開始前のディレクトリにあります。



23

cd標準入力を読み取りません。これが、最初の例が機能しない理由です。

xargsコマンド名、つまり独立した実行可能ファイルの名前が必要です。cdシェル組み込みコマンドである必要があり、それが実行可能ファイルである場合は効果がありません(そのディレクトリに変更できることと、自動マウント可能なディレクトリの潜在的な副作用を確認する以外は)。そのため、2番目の例は機能しません。


4

既存の良い答えに加えて、パイプが新しいプロセスを分岐することにも言及する価値があります。新しいプロセスには独自の作業ディレクトリがあります。したがって、これを実行しようとしても機能しません。

echo test | cd /

したがって、シェルがこのコマンドから戻った後は/フォルダーに移動しません。


パイプラインのすべてのコマンドは異なるプロセスで実行されます。そのため、およびがビルトインされa | bている場合でも、少なくとも1つはシェルプロセスで実行されませんが、どのコマンドであるかは保証されません。AT&Tで例えば、あるいは、あなたのコードがに/そこにあなたを取るので、現在のシェルプロセスで実行されます。abkshzshbash -O lastpipeb
ステファンシャゼラス

4

すでに与えられている正しい答えに加えて:bashを実行して、cdのような「コマンド」が何であるか知りたい場合は、typeを使用できます。

$ type cd
cd is a shell builtin

または理由:

$ type time
time is a shell keyword

たとえば、gnu timeは通常、すでにお気に入りのディストリビューションに含まれています:

$ which time
/usr/bin/time

オーケーオーケーあなたはアイデアを得る、そして一体何がタイプですか?

$ type type
type is a shell builtin

bashのマニュアルスニペットを次に示します。

       type [-aftpP] name [name ...]
          With no options, indicate how each name would be interpreted  if  used  as  a
          command name.  If the -t option is used, type prints a string which is one of
          alias, keyword, function, builtin,  or  file  if  name  is  an  alias,  shell
          reserved word, function, builtin, or disk file, respectively.  If the name is
          not found, then nothing is printed, and an exit status of false is  returned.
          If  the -p option is used, type either returns the name of the disk file that
          would be executed if name were specified as a command  name,  or  nothing  if
          ‘‘type  -t  name’’ would not return file.  The -P option forces a PATH search
          for each name, even if ‘‘type -t name’’ would not return file.  If a  command
          is  hashed,  -p  and -P print the hashed value, not necessarily the file that
          appears first in PATH.  If the -a option is used,  type  prints  all  of  the
          places  that  contain  an  executable  named name.  This includes aliases and
          functions, if and only if the -p option is  not  also  used.   The  table  of
          hashed  commands  is  not  consulted when using -a.  The -f option suppresses
          shell function lookup, as with the command builtin.  type returns true if any
          of the arguments are found, false if none are found.

0

他の人が言ったcdように、外部プログラムではなくシェル組み込みコマンドであるため、機能しません。したがって、パイプで入力できる標準入力はありません。

しかし、たとえそれが機能したとしても、あなたが望むことはしません:パイプは新しいプロセスを生成し、最初のコマンドの標準出力を2番目のコマンドの標準入力にリダイレクトします。したがって、新しいプロセスのみが現在の動作を変更しますディレクトリ; これが最初のプロセスに影響することはありませんでした。


2
2番目の段落は正しいです。しかし、最初の段落について:シェルの組み込みには標準入力がないと仮定するのはなぜですか?read通常(常に?)シェル組み込みです。cdstdin を無視するのは事実ですが、これは組み込みであるためではありません。
-dubiousjim

-2

もう1つのオプションは、1つのコマンドのstdoutを2番目のコマンドのコマンドライン引数として配置するバックティックであり、より移植性があり$(...)ます。例えば:

cd `echo $HOME`

またはより一般的に;

cd `anycommand -and whatever args`

バックティックの使用は、コマンドを実行してコマンドラインの出力を置き換えるシェルに依存することに注意してください。ほとんどのシェルがサポートしています。


3
OPは、彼/彼女の質問で、それが$(...)機能することをすでに述べています。代わりにバッククォートをお勧めするのは良いアドバイスではないと思います。クォートのルールがより複雑で、一般にエラーが発生しやすいためです。(Bashリファレンスマニュアルのセクション3.5.4「コマンドの置換」を参照してください。)
ruakh

$()はサポートされている場合は便利ですが、バックティックはさまざまなシェルやシステムでより広くサポートされています。しかし、これを「別のオプション」と言い換えるべきです。
セスノーブル

異なるシェル、はい; しかし、異なる「システム」?$(...)あるシステムではサポートするが別のシステムではサポートしないシェルは本当にありますか??
-ruakh

4
-1、質問にまったく答えません。
ベルンハルト

3
@ruakh&Seth:すべてのPOSIXシェルがサポートし$(…)ます。POSIXシェルを使用しないシステム(つまり、本物のBourneシェルを使用するシステム)は非常に古いものです。/bin/shBourneシェルがあり/usr/xpg4/bin/sh、POSIXシェルを取得するなどの別のパスが必要なシステムでさえ、現在ではまれです。古代のunix boxenを専門的に管理していない人にバックティックを勧めることは、彼らを傷つけています。
ジル「SO-悪であるのをやめる」
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.