リダイレクトとパイプ
前提:3-2が完了し、~/practiceの中にmemo.txtとvimtest.txtが存在する状態から始めます。ここまではnanoやvimでファイルの中身を「手で」書いてきましたが、Linuxには画面に表示されるはずの出力をファイルに流し込んだり、あるコマンドの結果を別のコマンドにそのまま渡したりする、蛇口と水道管のような仕組みがあります。それがリダイレクトとパイプです。このページではechoで文章を作りながら、> >> < | teeを体験します。
このページではSET 1〜3、合計30行のコマンドを上から順に叩きます。手打ち推奨(コピーは確認用)です。
SET 1 ― echoと > でファイルを作る
- $cd ~/practice
- $ls
- memo.txt vimtest.txt
- $echo "りんご"
- りんご
- $echo "りんご" > fruits.txt
- $cat fruits.txt
- りんご
- $echo "みかん" > fruits.txt
- $cat fruits.txt
- みかん
- $wc -l fruits.txt
- 1 fruits.txt
- $ls -l fruits.txt
- $file fruits.txt
- fruits.txt: ASCII text
1行目で練習用ディレクトリへ移動し、2行目のlsで、3-1・3-2で作ったmemo.txtとvimtest.txtだけが存在することを確認しておきます。
3行目のechoは、指定した文字列をそのまま画面に表示するだけのシンプルなコマンドです。ここに4行目のように>記号を足すと様子が一変します。>はリダイレクト※1と呼ばれる仕組みで、本来なら画面に出力されるはずの内容の行き先を、画面ではなく指定したファイルに変更します。5行目のcatで、たしかにファイルの中に「りんご」が書き込まれたことがわかります。
6行目でもう一度>を使って「みかん」を同じファイルに書き込むと、7行目のcatのとおり中身は「みかん」だけになり、「りんご」は跡形もなく消えています。>はファイルの中身を丸ごと新しい内容で置き換える、つまり上書きする記号だという点が、このページで最初に押さえるべきポイントです。8行目のwc -lで行数が1のままであることも数値で確認し、9行目のls -lでファイルサイズを、10行目のfileで、>で作られたファイルもnanoやvimで作ったのと同じ普通のテキストファイルであることを見ておきましょう。
水道管にたとえると、コマンドの出力は蛇口から出てくる水です。>を使うと、その水を画面という受け皿ではなく、指定したファイルという別のバケツに流し込みます。ただしバケツの中身はそのたびに空にしてから注ぐので、前の水(前の内容)は残りません。
SET 2 ― >> で追記、上書き事故を体験する
- $echo "りんご" > fruits.txt
- $wc -l fruits.txt
- 1 fruits.txt
- $echo "みかん" >> fruits.txt
- $echo "ぶどう" >> fruits.txt
- $cat fruits.txt
- りんご
- みかん
- ぶどう
- $wc -l fruits.txt
- 3 fruits.txt
- $echo "うっかり上書き" > fruits.txt
- $cat fruits.txt
- うっかり上書き
- $wc -l fruits.txt
- 1 fruits.txt
- $ls -l fruits.txt
1行目でfruits.txtを「りんご」だけの状態に作り直し、2行目のwc -lで行数がまだ1であることを数値でも確認します。3〜4行目では>ではなく>>(不等号2つ)を使っています。>>も出力の行き先をファイルに変える点は同じですが、中身を消さずに末尾に追記する点が違います。5行目のcatで確認すると、出力例のとおり「りんご」「みかん」「ぶどう」の3行が順番に積み上がっています。6行目のwc -lでも行数が3に増えたことを数値で確認しておきましょう。
7行目はわざと>を使って書き込んでいます。8行目のcatで確認すると、せっかく積み上げた3行がすべて消え、「うっかり上書き」の1行だけが残ってしまいました。これが「上書き事故」です。9行目のwc -lでも、行数が3から1に減ってしまったことが数値でもはっきりわかります。10行目のls -lでファイルサイズも小さくなっていることを確認すると、「上書き事故」が具体的に何を失ったのかがより実感できます。>と>>は見た目が矢印1本か2本かの違いしかありませんが、意味はまったく異なるため、大事なログファイルなどに書き込むときは記号を打ち間違えないよう特に注意してください。

あたしも一度、大事な作業ログを>>のつもりで>って打っちゃって、それまでの記録を全部消し飛ばしたことあるよ…。「追記したいときは矢印2本」って指の動きで覚えちゃうのがおすすめ! 不安なときはcatで中身を確認してから次に進む癖をつけよう。
SET 3 ― < で読み込み、| と tee でつなぐ
- $echo "りんご" > fruits.txt
- $echo "みかん" >> fruits.txt
- $echo "ぶどう" >> fruits.txt
- $wc -l < fruits.txt
- 3
- $cat fruits.txt | wc -l
- 3
- $cat fruits.txt | tee copy.txt
- りんご
- みかん
- ぶどう
- $cat copy.txt
- $wc -l fruits.txt copy.txt
- $ls -l fruits.txt copy.txt
- $cat fruits.txt copy.txt | wc -l
- 6
1〜3行目でfruits.txtを3行の状態に作り直します。4行目のwc -l < fruits.txtで使う<は>と向きが逆の記号で、ファイルの中身をコマンドの入力として読み込ませる働きをします。wc -lは本来キーボードからの入力を待つコマンドですが、<を使うことでfruits.txtの中身を直接読ませ、出力例のとおり行数3を数えさせています。
5行目のcat fruits.txt | wc -lで登場する|(縦棒、キーボードではShift+¥や\付近にあることが多い記号)はパイプ※2と呼ばれ、あるコマンドの出力をそのまま次のコマンドの入力に直結させます。水道管を蛇口から蛇口へじかにつなぐイメージで、catが出した3行をwc -lがそのまま受け取り、同じく3という結果を返しています。
6行目のcat fruits.txt | tee copy.txtのteeは、パイプの途中に取り付ける「分岐管」のようなコマンドです。teeは受け取った内容を画面にそのまま表示しながら(出力例のとおり)、同時に指定したファイル(ここではcopy.txt)にも書き込みます。7行目のcat copy.txtで、画面に出たのと同じ内容がファイルにも保存されていることを確認し、8行目のwc -lに2つのファイル名を並べて渡すと、それぞれの行数をまとめて数えてくれます。9行目のls -lでも同じく2つのファイルサイズを一度に比較しておきましょう。
最後に10行目のcat fruits.txt copy.txt | wc -lでは、catに2つのファイル名を並べて渡すと両方の中身をつなげて出力できる性質を利用し、そのままパイプでwc -lに渡しています。fruits.txtとcopy.txtはどちらも3行ずつなので、合計した行数として出力例のとおり6が返ってきます。複数のファイルをパイプでまとめて処理する感覚をここでつかんでおきましょう。
>と<は「コマンドとファイルの間」で水の向きを決める記号、|は「コマンドとコマンドの間」を水道管で直結する記号です。teeはその管の途中に付けたT字の分岐で、画面とファイルの両方に同時に水を流します。
まとめ
3-3では、出力の行き先を自在に変えるリダイレクトと、コマンド同士を直結するパイプという、Linuxらしい強力な仕組みを体験しました。このページで叩けるようになったコマンド・記号を一覧にまとめます。
| コマンド / 記号 | 何をするか | 覚え方 |
|---|---|---|
echo "文字列" | 文字列をそのまま出力する | echo = 声を返す(エコー) |
> | 出力先をファイルに変え、中身を上書きする | 矢印1本 = 上書き |
>> | 出力先をファイルに変え、末尾に追記する | 矢印2本 = 追記 |
< | ファイルの中身をコマンドの入力にする | >の逆向き = 読み込み |
| | あるコマンドの出力を次のコマンドの入力につなぐ | パイプ(水道管) |
tee ファイル名 | 出力を画面表示しつつファイルにも保存する | T字の分岐管 |
次のページ「3-4. grepで検索する」では、ここで作ったfruits.txtなどを使いながら、ファイルの中から目的の文字列だけを探し出すgrepを体験します。