&&と|の違いは何ですか bashスクリプトで?


12

2つの異なる結果を与える以下の2行を見てみましょう。

p=$(cd ~ && pwd) ; echo $p
p=$(cd ~ |  pwd) ; echo $p

この2つの違いは何ですか?


@heemaylありがとう。私の場合の違いを抽出してもらえますか?ありがとう。
ナムG VU

1
ヒント:両側のコマンド|はサブシェルで実行されます。
-heemayl

回答:


21

p=$(cd ~ && pwd)

  • コマンド置換、$()サブシェルで実行されます

  • cd ~ディレクトリを~(あなたのホーム)に変更し、cd成功した場合(&&)、pwdSTDOUTにディレクトリ名を出力します。したがって、保存さpれる文字列はホームディレクトリになります。/home/foobar

p=$(cd ~ | pwd)

  • 再び$()サブシェルを生成します

  • 両側のコマンドは|、それぞれのサブシェルで実行されます(そして、両方が同時に開始します)

  • そのcd ~サブシェルで実行されており、pwd中に別のサブシェル

  • pwdつまり、コマンドを実行した場所からSTDOUTのみを取得します。これは想像できる任意のディレクトリになります。したがってp、ホームディレクトリではなく、コマンドが呼び出されたディレクトリ名が含まれます。


コマンド間のパイプの目的は何ですか?cd ~出力を生成pwdせず、入力を読み取りません。
バーマー

2番目のコマンドは、基本的に同等(cd ~);p=$(pwd)です。
バーマー

@Barmarはい、それはOPが使用したものであり、私は彼のためにそれを説明しています。
heemayl

6

問題の核心は、どのように事業者である&&|2つのコマンドを接続します。

&&終了コードを介してコマンドを接続します。|ファイルディスクリプタ(STDIN、STDOUT)を介して2つのコマンドを接続しています。

最初に簡単にしましょう。割り当てを削除して、次のように記述できます。

echo $(cd ~ && pwd)
echo $(cd ~ | pwd)

コマンド実行サブシェルを削除して、これを分析することもできます。

$ cd ~ && pwd
$ cd ~ | pwd

&&

コマンドが実行されるディレクトリを表示するようにプロンプ​​トを変更すると、次のようPS1='\w\$ 'になります。

/tmp/user$ cd ~ && pwd
/home/user
~$ 
  • コマンドcd ~は、「現在のディレクトリ」を、コマンドを実行している実際のユーザーのホームに変更しました(/home/user)。
  • コマンドの結果が成功したため(終了コード0)、&&の後の次のコマンドが実行されます
  • そして、「現在の作業ディレクトリ」が印刷されます。
  • 実行中のシェルは、のプロンプトで示されるように変更されましpwdた。~~$

何らかの理由でディレクトリの変更が失敗した(終了コードが0ではない)場合(ディレクトリが存在しない、アクセス許可がディレクトリの読み取りをブロックする)、次のコマンドは実行されません。

例:

/tmp/user$ false && pwd
/tmp/user$ _ 

終了コード1 falseは、次のコマンドの実行を妨げます。

したがって、「コマンド1」の終了コードが「コマンド2」に影響を与えます。

次に、コマンド全体の効果:

/tmp/user$ echo $(cd ~ && pwd)
/home/user
/tmp/user$ _

ディレクトリは変更されましたが、サブシェル内$(…)では、変更されたディレクトリが印刷され/home/userますが、サブシェルが閉じるとすぐに破棄されます。pwdは初期ディレクトリ(/tmp/user)に戻ります。

|

これが起こることです:

/tmp/user$ cd ~ | pwd
/tmp/user
/tmp/user$ _

メタ文字|(真の演算子ではない)は、「パイプ」と呼ばれるものを作成するようにシェルに信号を送ります。(bashで)パイプの各側の各コマンド(|)は、各サブシェルの内側に設定されますコマンド、次に、左のコマンド。/dev/stdin正しいコマンドの入力ファイル記述子()は出力記述子(/dev/stdout)に接続され、その後、両方のコマンドが開始され、対話のために残されます。左のコマンド(cd -)には出力がありません。また、右のコマンド(pwd)には入力がありません。したがって、各サブシェル内でそれぞれが独立して実行されます。

  • cd ~1つのシェルのPWDを変更します。
  • pwd他のサブシェルの(完全に独立して)PWDを印刷します。

パイプが終了すると、各シェルでの変更は破棄され、外部サブシェルはpwdを変更していません。

これが、2つのコマンドが「ファイル記述子」によってのみ接続されている理由です。
この場合、何も送信されず、何も読み込まれません。

コマンド全体:

$ echo "$(cd ~ | pwd)"

コマンドが実行されたディレクトリのみを印刷します。


5

「|」の意味がわからない または「||」2番目の場合。

「|」シェルでは、あるコマンドの出力を別のコマンドの入力にパイプします。一般的な使用例は次のようなものです。 curl http://abcd.com/efgh | grep ijkl つまり、コマンドを実行し、別のコマンドを使用してコマンドの出力を処理します。

あなたが与える例では、「cd」は通常は出力を生成せず、「pwd」は入力を予期しないため、これはまったく無意味です。

「&&」および「||」ただし、パートナーコマンドです。これらは、ほとんどの言語で論理「and」および「or」演算子と同じ方法で使用されるように設計されています。ただし、実行される最適化により、シェルプログラミングパラダイムである特定の動作が提供されます。

論理「and」演算の結果を判断するには、最初の条件が成功した場合にのみ2番目の条件を評価する必要があります。最初の条件が失敗した場合、全体の結果は常にfalseになります。

論理「または」操作の結果を判断するには、最初の条件が失敗した場合にのみ2番目の条件を評価する必要があります。最初の条件が成功した場合、全体の結果は常に真になります。

そのため、シェルでは、完了して正常な結果コードを返したcommand1 && command2 command2ときにのみ実行されcommand1ます。あなたはしている場合はcommand1 || command2 command2ときに実行されますcommand1完了した場合は、command1エラーコードを返します。

別の一般的なパラダイムはcommand1、テストコマンドを使用することです。これにより、if / thenステートメントが1行生成されます。たとえば、次のようになります。

[ "$VAR" = "" ] && VAR="Value if empty"

変数が現在空の場合に変数に値を割り当てる(長く巻かれた)方法です。

Stack Exchangeの他の場所で、このプロセスの使用例が数多くあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.