[図解]リダイレクト操作(>hoge 2>&1等)の自分なりにしっくりきた説明

# はじめに
以下のようなbashでのリダイレクト操作に関して、個人的に最もしっくりきた説明を記載します。

```bash
cmd > test.log
cmd 2> test.log
cmd > test.log 2>&1
cmd > /dev/null 2>&1
cmd 2>&1 > test.log
cmd1 2>&1 | cmd2
cmd1 2>&1 1>/dev/null | cmd2
cmd 3>&2 2>&1 1>&3
```

以下に記載する内容は**「こう考えると上記各式の違いを理解できる」**、という内容になります。
より詳しい仕様については多くの他サイトで説明されていますので、そちらをご覧ください。


# 目次
[1.リダイレクトの3つのルール](#1リダイレクトの3つのルール)
[2.イメージ図](#2イメージ図)
[3.各リダイレクト操作の意味を解説](#3各リダイレクト操作の意味を解説)
[3.1.cmd > test.log](#31cmd--testlog)
[3.2.cmd 2> test.log](#32cmd-2-testlog)
[3.3.cmd > test.log 2>&1](#33cmd--testlog-21)
[3.4.cmd > /dev/null 2>&1](#34cmd--devnull-21)
[3.5.cmd 2>&1 > test.log](#35cmd-21--testlog)
[3.6.cmd1 2>&1 | cmd2](#36cmd1-21--cmd2)
[3.7.cmd1 2>&1 1>/dev/null | cmd2](#37cmd1-21-1devnull--cmd2)
[3.8.cmd 3>&2 2>&1 1>&3](#38cmd-32-21-13)
[まとめ](#まとめ)

# 1.リダイレクトの3つのルール

冒頭で述べた各式の違いを理解するのに覚える必要があるルールは以下３つです。

ルール１　A>hoge （Aの向き先をhogeにする)
ルール２　A>&B  (Aの向き先をBが現在指し示す先にする(Bと同じ向き先を向くようにする))
ルール３　リダイレクト記述が複数ある場合左から処理される

※A, Bは数字。Aを省略した場合、A=1とみなされる。

# 2.イメージ図
リダイレクト操作のイメージ図は以下になります。
![スクリーンショット 2020-01-15 13.14.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191873/6f2de678-7de7-3ef0-0166-e4f060c8ced4.png)

※そもそも標準出力、標準エラー出力って何？と思った方は、以下をご覧ください。詳しく解説されています。
[標準入力・標準出力ってなに?](https://qiita.com/angel_p_57/items/03582181e9f7a69f8168)

それでは、このイメージ図と３つのルールでリダイレクト操作を考えます。

# 3.各リダイレクト操作の意味を解説
では３つのルールとイメージ図を使って、冒頭の各式をひもといていきます。

## 3.1.cmd > test.log
ルール１ A>hoge、Aの向き先をhogeにする。ただしAを省略した場合は1とみなされる。
従って、cmd 1> test.logと同じになり、以下のようになります。

![スクリーンショット 2020-01-15 13.03.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191873/7d804d71-4da3-32de-e753-aaafde502edc.png)


## 3.2.cmd 2> test.log
ルール１ A>hoge、Aの向き先をhogeにする。
以下のように2の向き先をtest.logにします。

![スクリーンショット 2020-01-15 13.03.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191873/7aa74722-1328-f60b-19c6-6d8e59174ee4.png)


## 3.3.cmd > test.log 2>&1
ルール３、リダイレクト記述が複数ある場合左から処理される、ため、まずはcmd > test.logを見ます。
これは、ルール１ A>hoge、Aの向き先をhogeにする(ただしA省略時は1とみなす)、ので以下のようになります。

![スクリーンショット 2020-01-15 13.03.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191873/312f242e-4f74-6043-3625-037534a07401.png)

続いて 2>&1。
ルール２ A>&B、Aの向き先をBが現在指し示す先にする。
1が現在指し示す先はtest.logです。そのため2の向き先をtest.logにする（以下)。

![スクリーンショット 2020-01-15 13.05.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191873/50be54c2-9f1c-e984-7707-ffbcc3188cd3.png)


結果として、1(標準出力の内容)も2(標準エラー出力の内容)もtest.logに出力される。

## 3.4.cmd > /dev/null 2>&1
/dev/nullにリダイレクトされたものは全て棄てられます。どこにも出力されません。
式の形としては[3.3.cmd > test.log 2>&1](#33cmd--testlog-21)と同じですので、
結果として1(標準出力の内容)も2(標準エラー出力の内容)も棄てられます。

## 3.5.cmd 2>&1 > test.log
これは[3.3.cmd > test.log 2>&1](#33cmd--testlog-21)を逆の順番で書いた場合。
ルール３に従い左から順に処理します。
ルール２ A>&B、Aの向き先をBが現在指し示す先にする、ので2の向き先を1が現在指し示す先にします(以下)。

![スクリーンショット 2020-01-15 13.07.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191873/38889a60-d5dd-4225-e6af-af60dc72fd3d.png)


続いて、 > test.logを処理します。
ルール１ A>hoge、Aの向き先をhogeにする(ただしA省略時は1とみなす)、ので1>test.logは以下のようになります。

![スクリーンショット 2020-01-15 13.09.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191873/90370f8d-398d-2f98-ea70-dd468079e968.png)


結果として、1(標準出力の内容)はtest.logに出力され、2(エラー出力の内容)は標準出力(画面)に出力されます。
このように式の順序を変えると全く異なる結果になります。

## 3.6.cmd1 2>&1 | cmd2
パイプ（|）は、標準出力のみを渡します。そのため標準エラー出力もパイプで渡したい場合このようにします。
ルール２ A>&B、Aの向き先をBが現在指し示す先にする、ので2の向き先を1が現在指し示す先にします(以下)。

![スクリーンショット 2020-01-14 14.59.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191873/c683af44-f8fd-6e4b-7f92-d4638ed2d208.png)

これで1の内容2の内容両方が標準出力へ出力され、パイプでcmd2へ渡されます。

## 3.7.cmd1 2>&1 1>/dev/null | cmd2
標準エラー出力だけをパイプで渡したい場合このようにします。
ルール２ A>&B、Aの向き先をBが現在指し示す先にする、ので2の向き先を1が現在指し示す先にします(以下)。

![スクリーンショット 2020-01-14 15.20.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191873/67a9d5d5-1f7c-c550-fb9e-3ab5cebfa252.png)


続いて1>/dev/nullは、
ルール１ A>hoge、Aの向き先をhogeにする、ので以下になります。

![スクリーンショット 2020-01-14 15.19.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191873/98fae36f-798c-1a5f-e6cb-c20e6afbd1f5.png)

結果として、1の内容は棄てられ、2（エラー出力）のみが標準出力に出力され、パイプでcmd２へ渡されます。

## 3.8.cmd 3>&2 2>&1 1>&3
これは標準出力と標準エラー出力の内容を入れ替えます。
ルール２ A>&B、Aの向き先をBが現在指し示す先にする、およびルール３に従い左から順に処理します（以下)。

![スクリーンショット 2020-01-15 13.10.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191873/a5d80c6c-2be0-624e-c91d-a795d0493386.png)


結果として、2の内容が標準出力へ、1の内容が標準エラー出力へ出力されます。

# まとめ
本記事では「冒頭で記載したリダイレクトを含む式」の違いを理解するための考え方を記載しました。

なおリダイレクトのその他の詳細な説明に関しては、他にたくさん説明されているサイトがあるのでそちらをご参照ください。

# 参考文献
[標準入力・標準出力ってなに?](https://qiita.com/angel_p_57/items/03582181e9f7a69f8168)