Linuxコマンドの連結の挙動



手順書とか作っててLinux系のコマンドとか複数行に分けて書くのが面倒だったので、一行で書きたい！
→ コマンドを`&`でつないだけどどうやら実行結果が思い通りに行かないので備忘録的にLinuxコマンドの連結の挙動をまとめる

## 事前準備
1. 異常終了を返すシェルを用意する

    ```sh:false.sh
    #!/bin/bash/
    #実行されたことがわかるように文字列出力
    echo "this shellscript is return false"
    #異常終了のステータス値
    exit 1
    ```
1. 正常終了を返すシェルを用意する


    ```sh:true.sh
    #!/bin/bash/
    #実行されたことがわかるように文字列出力
    echo "this shellscript is return true"
    #正常終了のステータス
    exit 0
    ```

## Linuxコマンドの連結の種類

```
1. ;
2. &$
3. &
4. |
5. ||
```

## 検証
### `;`(セミコロン)

- <font color="red">実行結果に関わらず</font>とにかく書いたコマンドを次々に実行しまくる

```
$ bash false.sh ; echo congraturation!!!
this shellscript is return false
congraturationbash!
```

異常終了を表す1を返すbashファイルを実行しても後続の`echo`も実行される

もちろんどんなに繋げても

```
$ bash false.sh ; bash false.sh ; bash false.sh ; bash false.sh ; bash false.sh ; bash false.sh ; bash false.sh ; bash false.sh ; echo congraturation!
this shellscript is return false
this shellscript is return false
this shellscript is return false
this shellscript is return false
this shellscript is return false
this shellscript is return false
this shellscript is return false
this shellscript is return false
congraturation!
```

### `&&`(アンド×2)

先ほどとは打って変わってこちらは<font color="red">正常終了したら後続のコマンドを実行する</font>ので、実行結果が異常終了した時点で実行が止まります


```
$ bash false.sh  && echo congraturation!
this shellscript is return false
```

もちろん`echo`は実行されない


```
$ bash true.sh && bash false.sh && echo congraturation!
this shellscript is return true
this shellscript is return false
```

最後の`echo`までは到達しない


### `&`(アンド)

<font color="red">`&&`と混同しないように!</font>
&だけでは同時(並列)実行になってしまうので、例えば下記のように

1. hogeディレクトリを作成
1. hogeディレクトリに移動
1. gitのリポジトリをclone


見たいなことがしたいときに↓のようにしてしまうと普通にカレントディレクトリにリポジトリをcloneされるっということが起きかねません！

```
$ mkdir hoge/ & cd hoge/ & git clone {ripository}
```

ということで本当に並列で実行されているのか確認するために下記のようなシェルを用意してください。

```bash:hoge.sh
#!/bin/bash/

for i in 1 2 3 4 5 6 7 8 9
do 
    echo I\'m hoge! current roop is $i time .
    sleep 1
done
```

```bash:fuga.sh
#!/bin/bash/

for i in 1 2 3 4 5 6 7 8 9
do 
    echo I\'m fuga! current roop is $i time .
    sleep 1
done
```

並列実行されているなら交互に`echo`の内容を出力するはず！

```
$ bash fuga.sh & bash hoge.sh
```

```
I'm fuga! current roop is 1 time .
I'm hoge! current roop is 1 time .
I'm fuga! current roop is 2 time .
I'm hoge! current roop is 2 time .
I'm fuga! current roop is 3 time .
I'm hoge! current roop is 3 time .
I'm fuga! current roop is 4 time .
I'm hoge! current roop is 4 time .
I'm fuga! current roop is 5 time .
I'm hoge! current roop is 5 time .
I'm fuga! current roop is 6 time .
I'm hoge! current roop is 6 time .
I'm fuga! current roop is 7 time .
I'm hoge! current roop is 7 time .
I'm hoge! current roop is 8 time .
I'm fuga! current roop is 8 time .
I'm fuga! current roop is 9 time .
I'm hoge! current roop is 9 time .
```

綺麗に出力されました🎉

### `||`(パイプ×2)

`&&`とは真逆!
<font color="red">異常終了したら後続のコマンドを実行する</font>ので、実行結果が正常終了した時点で実行が止まります。


```
$ bash true.sh || echo something error!
this shellscript is return true
```

正常終了するので`echo`は実行されない

```bash
$ bash false.sh || echo something error!
this shellscript is return false
something error!
```

異常終了した場合は後続のコマンドが実行される


```bash
$ bash false.sh || bash true.sh || echo something error!
this shellscript is return false
this shellscript is return true
```

最後の`echo`までは到達しない

### `|` パイプ

今までのものと比べてちょっと変わっている
<font color="red">前のコマンドの標準出力結果を後続のコマンドに引き渡す！</font>

これは所感ですが基本`grep`でしか使うことがあんまりなさそう....あとは`xargs`か`more`くらい

一応例としては下記みたいな都道府県名と県庁所在地がペアで羅列されているテキストがある時、この中から東京の情報だけ取得したい!という時にgrepと組み合わせることでそれが実現できます

```txt:prefecture.txt
北海道(ほっかいどう) 札幌(さっぽろ)
青森県(あおもり) 青森(あおもり)
岩手県(いわて) 盛岡(もりおか)
宮城県(みやぎ) 仙台(せんだい)
秋田県(あきた) 秋田(あきた)
山形県(やまがた) 山形(やまがた)
福島県(ふくしま) 福島(ふくしま)
茨城県(いばらき) 水戸(みと)
栃木県(とちぎ) 宇都宮(うつのみや)
群馬県(ぐんま) 前橋(まえばし)
埼玉県(さいたま) さいたま
千葉県(ちば) 千葉(ちば)
東京都(とうきょう) 東京(とうきょう)
神奈川県(かながわ) 横浜(よこはま)
新潟県(にいがた) 新潟(にいがた)
富山県(とやま) 富山(とやま)
石川県(いしかわ) 金沢(かなざわ)
福井県(ふくい) 福井(ふくい)
山梨県(やまなし) 甲府(こうふ)
長野県(ながの) 長野(ながの)
岐阜県(ぎふ) 岐阜(ぎふ)
静岡県(しずおか) 静岡(しずおか)
愛知県(あいち) 名古屋(なごや)
三重県(みえ) 津(つ)
滋賀県(しが) 大津(おおつ)
京都府(きょうと) 京都(きょうと)
大阪府(おおさか) 大阪(おおさか)
兵庫県(ひょうご) 神戸(こうべ)
奈良県(なら) 奈良(なら)
和歌山県(わかやま) 和歌山(わかやま)
鳥取県(とっとり) 鳥取(とっとり)
島根県(しまね) 松江(まつえ)
岡山県(おかやま) 岡山(おかやま)
広島県(ひろしま) 広島(ひろしま)
山口県(やまぐち) 山口(やまぐち)
徳島県(とくしま) 徳島(とくしま)
香川県(かがわ) 高松(たかまつ)
愛媛県(えひめ) 松山(まつやま)
高知県(こうち) 高知(こうち)
福岡県(ふくおか) 福岡(ふくおか)
佐賀県(さが) 佐賀(さが)
長崎県(ながさき) 長崎(ながさき)
熊本県(くまもと) 熊本(くまもと)
大分県(おおいた) 大分(おおいた)
宮崎県(みやざき) 宮崎(みやざき)
鹿児島県(かごしま) 鹿児島(かごしま)
沖縄県(おきなわ) 那覇(なは)
```

- まずはcatだけの出力
    - ※長いので出力結果割愛しています。

```
$ cat prefecture.txt

北海道(ほっかいどう) 札幌(さっぽろ)
青森県(あおもり) 青森(あおもり)
岩手県(いわて) 盛岡(もりおか)
宮城県(みやぎ) 仙台(せんだい)
秋田県(あきた) 秋田(あきた)
山形県(やまがた) 山形(やまがた)
福島県(ふくしま) 福島(ふくしま)
        :
        :
        :
```

- `|`で出力結果を`grep`に渡す

```
$ cat prefecture.txt | grep 東京都
東京都(とうきょう) 東京(とうきょう)
```

# おわり


##### 参照
[Linuxコマンドを連続して使うには](https://qiita.com/egawa_kun/items/714394609eef6be8e0bf)