はじめに

本記事ではLinuxコマンド「|」(パイプ)と「;」(セミコロン)についてまとめます。
コマンドの挙動で勘違いしていた部分があったので、調べることにしました。

1. コマンド「|」(パイプ)

ここでは、コマンド「|」(パイプ)について、実行例などを基に説明します。

1-1. コマンド「|」(パイプ)とは

パイプとは、Linuxコマンドの標準出力結果を次のコマンドに渡すために使用されるコマンドです。
パイプを使用することで複数のコマンドを1つのプログラムのように動かすことができます。
パイプの正式名称は「パイプライン」と呼ばれます。

1-2. コマンド「|」(パイプ)の書式

コマンド「|」(パイプ)の書式は以下の通りです。

$ (command_1) | (command_2) | … | (command_n)

1-3. 実行例

「|」(パイプ)でよく使用されるパターンとして、標準出力の内容を操作することが多いです。
実際に、このコマンドが使用される実行例を紹介します。

例1:「grep」コマンドとの組み合わせ

「grep」は、文字列を検索するLinuxコマンドです。

  • テキストファイルから特定の文字列で「grep」を行う

①テキストの中身を表示する

[C:\Users\sp-taro]$ cat sample1.txt
aaaaa
bbbbb
ccccc

②文字列「aaaaa」でgrepを行う

[C:\Users\sp-taro]$ cat sample1.txt | grep aaaaa
aaaaa

 ⇒条件に一致する文字列が出力されます。

③文字列「abc」でgrepを行う

[C:\Users\sp-taro]$ cat sample1.txt | grep abc
[C:\Users\sp-taro]$

 ⇒条件に一致する文字列がないので、何も出力されませんでした。

例2:「tee」コマンドとの組み合わせ

「tee」コマンドは、標準出力の結果をファイルに出力できるコマンドです。

● カレントディレクトリに指定した文字列を含むファイル名を別ファイルに書き出す

①カレントディレクトリに存在するファイルを確認する

[C:\Users\sp-taro]$ ls -l
total 8
-rw-rw-r-- 1 dba dba 19 Aug 22 19:26 sample1.txt
-rw-rw-r-- 1 dba dba 19 Aug 22 19:26 sample2.txt
-rw-rw-r-- 1 dba dba  0 Aug 22 20:15 test1.txt
-rw-rw-r-- 1 dba dba  0 Aug 22 20:15 test2.txt

②「find」コマンドを使用し、指定した文字列を含むファイル名を別ファイルに出力する

[C:\Users\sp-taro]$ find test* | tee sample3.txt
test1.txt
test2.txt

③カレントディレクトリに存在するファイルを確認する。

[C:\Users\sp-taro]$ ls -l
total 12
-rw-rw-r-- 1 dba dba 19 Aug 22 19:26 sample1.txt
-rw-rw-r-- 1 dba dba 19 Aug 22 19:26 sample2.txt
-rw-rw-r-- 1 dba dba 20 Aug 22 20:21 sample3.txt ←新規作成された
-rw-rw-r-- 1 dba dba  0 Aug 22 20:15 test1.txt
-rw-rw-r-- 1 dba dba  0 Aug 22 20:15 test2.txt

 ⇒新たにsample3.txtというファイルが作成されました。

④sample3.txtの中身を確認する

[C:\Users\sp-taro]$ cat sample3.txt
test1.txt
test2.txt

⇒「find」コマンドで指定した文字列を含むファイル名が書き出されています。

2. コマンド「;」(セミコロン)について

ここでは、コマンド「;」(セミコロン)について、実行例などを基に説明します。

2-1. コマンド「;」(セミコロン)とは

セミコロンとは、複数のコマンドを続けて実行する際に使用されるLinuxコマンドです。
コマンドが終了してから次のコマンドが実行されます。

2-2. コマンド「;」(セミコロン)の書式

コマンド「;」(セミコロン)の書式は以下の通りです。

$ (command_1) ; (command_2) ; … ; (command_n)

2-3. 実行例

「;」(セミコロン)は、単純にコマンドを複数続けて実行するだけなので、よく使われるパターンみたいなものはなさそうです。
なので、複数コマンドを実行したときにコマンドが終わるまで次のコマンドが待機されるか確認してみたいと思います。

  • 「時刻取得」→「30秒待機」→「時刻取得」を1コマンドで実行する。
[C:\Users\sp-taro]$ date ; sleep 30s ; date
Thu Aug 25 18:25:20 JST 2022 ←コマンド1実行結果
Thu Aug 25 18:25:50 JST 2022 ←コマンド3実行結果

 ⇒コマンド1で時刻を取得してから、コマンド3で再度時刻を取得するまで30秒待機していることがわかります。

3. それぞれのコマンドの挙動の違い

ここでは、「はじめに」
で記載したコマンドの挙動で勘違いしていた部分についてまとめます。

やろうとしたこと

コマンド1で環境変数に値を設定し、コマンド2で設定した変数の値を使う。
2つのコマンドはパイプでつなげる。

実行してみた

export VAR=sample | echo $VAR
[C:\Users\sp-taro]$ export VAR=sample | echo $VAR

⇒結果、何も表示されませんでした。

セミコロン「;」で実行してみた

export VAR=sample ; echo $VAR
[C:\Users\sp-taro]$ export VAR=sample ; echo $VAR
sample

 ⇒ちゃんと表示されました。

上記結果より、
セミコロンはコマンドを連続で実行するのに対し、パイプは標準出力された値を次のコマンドに渡すだけであって、実際にコマンドが実行されているわけではなさそうです。

改めてですが、パイプは「標準出力した結果を次のコマンドに渡す」処理です。
なので今回のexportのように、出力されるものがない場合は次のコマンドに渡す値はありません。
パイプとして値を渡していないのはわかりますが、exportが実行されていれば内部的には変数が設定されるので、値が表示される想定でした。

そもそもセミコロンで実行すれば何も問題なかったですが、、、
こういう挙動をする、ということで気を付けないといけませんね。

さいごに

Linuxコマンドのパイプセミコロンと、それぞれのコマンドの挙動の違いについてまとめました。
他にもLinuxにはたくさんのコマンドがあるので、興味があれば是非調べてみてください。
ご覧いただきありがとうございました。