標準入出力のリダイレクト

## 標準出入力とは

**【標準入力】⇒【コマンド】⇒【標準出力 / 標準エラー出力】**

標準入力：プログラムの標準的な入力。通常はキーボードが使われる。
標準出力：プログラムの標準的な出力。通常は端末ディスプレイが使われる。
標準エラー出力：プログラムのエラーメッセージを出力するための標準的な出力。通常は端末ディスプレイが使われる。

**ファイル / キーボード etc.　⇒【コマンド】⇒　ファイル / ディスプレイ etc.**

## リダイレクトとは

標準入出力先を変更する機能のこと

## 標準入力のリダイレクト

ファイルをコマンドの標準入力に入力

```shell:書式
【コマンド】 < 【ファイル名】
```

`Hello World` と書かれている file.txt を `cat` コマンドの標準入力に入力

```shell
$ cat < file.txt
Hello World
```

`cat` コマンドの場合、ファイル指定でも入力リダイレクトと得られる結果は同じ

```shell
$ cat file.txt
Hello World
```

## 標準出力のリダイレクト

コマンドの標準出力をファイルに出力

```shell:書式
【コマンド】 > 【ファイル名】
```

`Hello World` を file.txt に書き込む

```shell
$ echo 'Hello World' > file.txt
$ cat file.txt
Hello World
```

## 標準エラー出力のリダイレクト

コマンドの標準エラー出力をファイルに出力

```shell:書式
【コマンド】 2> 【ファイル名】
```

エラーメッセージをファイルに保存

```shell
$ ls ./not/exists/directory 2> error.txt
$ cat error.txt
ls: cannot access ./not/exists/directory: No such file or directory
```

標準出力と標準エラー出力の違いは、片方をファイルに出力することで明確になる

```shell
# コマンドがエラーであれば、標準出力をファイルに出力しても、エラーメッセージは表示される
$ ls ./not/exists/directory > result.txt
ls: cannot access ./not/exists/directory: No such file or directory

# コマンドがエラーでなければ、標準エラー出力をファイルに出力しても、標準出力は表示される
$ ls ./exists/directory 2> error.txt
file.txt
```

標準出力と標準エラー出力をそれぞれ別ファイルにリダイレクト

```shell
# コマンドがエラーではないので、error.txt には何も出力されていない
$ ls ./exists/directory > result.txt 2> error.txt
$ cat result.txt
file.txt
$ cat error.txt

# コマンドがエラーなので result.txt には何も出力されていない
$ ls ./not/exists/directory > result.txt 2> error.txt
$ cat result.txt
$ cat error.txt
ls: cannot access ./not/exists/directory: No such file or directory
```

## 標準出力と標準エラー出力をまとめてリダイレクト

```shell:書式
【コマンド】 > 【ファイル名】 2>&1
```

`ls` コマンドの標準出力と標準エラー出力を result.txt にまとめてリダイレクト

```shell
# コマンドがエラーではないので、result.txt には標準出力のみ出力されている
$ ls ./exists/directory > result.txt 2>&1
$ cat result.txt
file.txt

# コマンドがエラーなので、result.txt には標準エラー出力が出力されている
$ ls ./not/exists/directory > result.txt 2>&1
$ cat result.txt
ls: cannot access ./not/exists/directory: No such file or directory
```

標準入出力の数値

|標準入力|標準出力|標準エラー出力|
|:-----:|:-----:|:-----------:|
|0|1|2|

`&1` は標準出力のことを指し、`2>&1` とは標準エラー出力と標準出力を同じファイルへリダイレクト指定すること


## コマンドの標準出力をファイルに追加出力

`>` による標準出力のリダイレクトは、指定したファイル名と同一のファイルが存在する場合に上書きされる

```shell
# 123 と記述された number.txt というファイルを作成
$ echo 123 > number.txt
$ cat number.txt
123

# 同じファイル名で出力すると、ファイルの内容が上書きされている
$ echo 456 > number.txt
$ cat number.txt
456
```

`>` を `>>` にすることで、上書きではなく、ファイル末尾への追記になる

```shell:書式
【コマンド】 >> 【ファイル名】
```

`123` と書き込まれた number.txt に `456` を追記

```shell
$ echo 123 > number.txt
$ echo 456 >> number.txt
$ cat number.txt
123
456
```

新規ファイルに対して `>>` を使用しても問題ないため、常に `>>` を使用しておけば、上書きの心配はない

## リダイレクト記法まとめ

ファイルをコマンドの標準入力に入力

```shell
【コマンド】 < 【ファイル名】
```

コマンドの標準出力をファイルに出力

```shell
【コマンド】 > 【ファイル名】
```

コマンドの標準出力をファイル末尾に追記

```shell
【コマンド】 >> 【ファイル名】
```

コマンドの標準エラー出力をファイルに出力

```shell
【コマンド】 2> 【ファイル名】
```

コマンドの標準エラー出力をファイル末尾に追記

```shell
【コマンド】 2>> 【ファイル名】
```

コマンドの標準出力と標準エラー出力をともにファイルに出力

```shell
【コマンド】 > 【ファイル名】 2>&1
```

## /dev/null

`Linux` ではリダイレクト先として利用される特別なファイルで、下記の性質を持つ

- 入力先として指定しても、何も内容を返さない
- 出力先として指定しても、書き込んだデータはどこにも保存されず消滅する

```shell
# /dev/nullファイルの確認
$ ls -l /dev/null
crw-rw-rw-. 1 root root 1, 3 May  8 03:09 /dev/null
```

入力先として指定しても、何も内容を返さない

```shell
$ cat < /dev/null
$ （何も表示されない）
```

出力先として指定しても、書き込んだデータはどこにも保存されず消滅する

```shell
$ echo 'Hello World' > /dev/null
$ （何も表示されない）
```