Linuxの複数コマンドの実行制御と引用符について


Linuxのコマンドを実行するとき複数のコマンドを並べて実行したいときがあると思います。複数コマンドの実行制御方法について知っておくことで、できることの幅が広がります。

## 複数コマンドの実行制御方法

複数コマンドの実行制御方法は以下の様なものがあります。

| 方法                      | 構文例                           | 説明                                                                            |
|---------------------------|-----------------------------------|---------------------------------------------------------------------------------|
| シーケンシャル実行（`;`）   | `command1; command2; command3`     | 成功・失敗に関わらず、順番にすべてのコマンドを実行します。                        |
| 成功時の実行（`&&`）       | `command1 && command2`             | 最初のコマンドが成功した場合のみ次のコマンドを実行します。                        |
| 失敗時の実行（`\|\|`）       | `command1 \|\| command2`             | 最初のコマンドが失敗した場合のみ次のコマンドを実行します。                        |
| バックグラウンド実行（`&`）| `command1 & command2 &`            | コマンドをバックグラウンドで実行し、同時に複数のコマンドを実行します。            |
| サブシェル（`()`）          | `(cd /path/to/dir && ls)`          | サブシェルでコマンドを実行し、親シェルに影響を与えません。                        |
| グループコマンド（`{}`）    | `{ command1; command2; }`          | コマンドをグループ化し、1つのシェルで実行します。                                |
                              

### シーケンシャル実行
シーケンシャル実行は複数のコマンドを順番に1つずつ実行する方式を指します。具体的には、あるコマンドが終了してから次のコマンドが実行される形になります。
この方式では、各コマンドが成功したか失敗したかに関わらず、指定された順番で次のコマンドが実行されます。

以下のように、複数のコマンドを ; で区切ることで、シーケンシャル実行が可能です。
```
date;pwd
```
この例だと今日の日付を表示したあとにカレントディレクトリの絶対パスを表示します。

### 成功時の実行 &&
&&でコマンドを並べるとあるコマンドが正常に終了した場合にのみ、次のコマンドを実行します。
コマンドが成功した場合に次のステップを実行したい場合や依存関係のある操作（例：ビルドが成功したらデプロイを開始するなど）に使われます。

```
cp file1.txt /backup/ && echo "File copied successfully."
```
この例では、cp コマンドで file1.txt のコピーが成功した場合にのみ、echo "File copied successfully." が実行されます。もし cp が失敗した場合は、echo コマンドは実行されません。

### 失敗時の実行 ||
あるコマンドが失敗したときにのみ、次のコマンドを実行する方法です。Linuxのシェルでは、||（論理OR）を使用して実現します。

コマンドが失敗した場合にエラーメッセージや代替処理を行いたいときやファイルやディレクトリが存在しなかった場合に作成する処理、リソースがなかった場合に別の操作を行う場合などに使われます。

```
ls /nonexistent_directory || echo "Directory not found"
```
この例では、ls コマンドで /nonexistent_directory をリストしようとしますが、ディレクトリが存在しない場合（ls コマンドが失敗）、echo "Directory not found" が実行されます。

もしディレクトリが存在して ls が成功した場合、echo コマンドは実行されません。


### バックグラウンド実行 &
コマンドに&をつけて実行することでバックグラウンド実行ができます。バックグラウンドで実行することにより同じシェルを使いながら他のコマンドを実行できるようになります。

```
sleep 60 &
```
この例では、sleep 60 コマンドがバックグラウンドで実行され、60秒間の待機がバックグラウンドで行われます。この間、ユーザーは他のコマンドをシェルで実行することができます。

以下の様に複数コマンドを同時にバックグラウンドで実行することも可能です。

```
command1 & command2 &

```
長時間かかる処理を実行している間に、別の作業をシェルで行いたいときやシステムの複数のプロセスを同時に実行し、時間の効率化を図りたいときに便利です。

### サブシェル ()

()を使用することで現在のシェルプロセスとは別に新しいシェル（子プロセス）を作成して、その中でコマンドを実行する方法です。サブシェル内で実行されたコマンドは、親シェルの環境（変数やディレクトリの状態）には影響を与えません。

サブシェルを使用することで、特定の操作を隔離して実行できるため、安全に処理を行いたい場合などに便利です。

```
pwd                # 現在のディレクトリを表示
(cd /tmp && ls)    # サブシェル内で /tmp に移動し、内容を表示
pwd                # サブシェルが終了したので、元のディレクトリに戻る
```
上記の例では、cd /tmp で /tmp に移動していますが、これはサブシェル内の操作なので、親シェルのカレントディレクトリには影響を与えず、サブシェル終了後も親シェルのカレントディレクトリは変わりません。

### グループコマンド ｛｝
複数のコマンドを同じシェルプロセス内でグループ化して実行する方法です。コマンドを中括弧 {} で囲むことで、複数のコマンドを1つのグループとしてまとめて実行することができます。

グループコマンドは、サブシェルとは異なり、同じシェル環境内で実行されるため、環境の変更（変数やカレントディレクトリの変更など）が親シェルに反映されます。

```
pwd                    # 現在のディレクトリを表示
{ cd /tmp; ls; }       # /tmp ディレクトリに移動し、その内容を表示
pwd                    # グループコマンドでは、ディレクトリ変更が親シェルに影響する
```

**グループコマンドの活用例**
・変数の設定と参照: グループ内で変数を設定し、親シェルにその値を反映させたい場合に使用します。
・ディレクトリ操作のまとめ: ディレクトリ移動とその中での操作をまとめて実行し、後のコマンドに反映させる際に便利です。
・複数コマンドの一括実行: 連続して実行したい複数のコマンドを1つのグループとしてまとめて管理することができます。

## 引用符

### シングルクォーテーション '
シングルクォーテーションの中は、すべて文字列として扱われます。変数や特殊文字（例: $ や * など）が解釈されず、そのまま出力されます。

```
echo 'Hello $USER'
Hello $USER
```

変数 $USER が解釈されずに、文字列としてそのまま表示されます。

### ダブルクォーテーション "
ダブルクォーテーションも文字列として扱われますが、ダブルクォーテーション内に変数がある場合は展開されます。またバッククォーテーションが使われている場合も展開されます。

```
echo "Hello $USER"
Hello <ユーザー名>
```
この場合、変数 $USER が解釈され、実際のユーザー名が表示されます。

$記号などをそのまま使いたい場合はバックスラッシュ「\」を展開させたくない文字の前に付けます。バックスラッシュ直後の文字はすべて通常の文字列として扱われます。バックスラッシュはエスケープ文字とよばれます。

### バッククォーテーション 　`または $( )
バッククォートや $() を使うと、その中で実行されたコマンドの結果が展開されます。
コマンドの出力を文字列に含めたい場合に使用します。
```
echo `date`
または
echo $(date)
```

コマンド date が実行され、その結果が表示されます。