【Linux】cat << EOF > [ファイル名] というコマンドの解説

## 前置き

最近使用した`cat << EOF > [ファイル名]`というコマンドについて調べてみた。



## catコマンド

`cat << EOF > [ファイル名]`の`cat`に当たる部分の説明をします。



### 書式



```
cat [,オプション/]... [,ファイル/]...  
```



### 機能説明



>ファイル (複数可) の内容を結合して標準出力に出力します。
>
>ファイルの指定がない場合や FILE が - の場合, 標準入力から読み込みを行います。



http://linuxjm.osdn.jp/html/GNU_coreutils/man1/cat.1.html



ファイルを連結して表示できるなんて知らなかった。標準入力から読み込みなんてもっと知らなかった。



### catのhelp



```
$ cat --help
使用法: cat [オプション]... [ファイル]...
Concatenate FILE(s) to standard output.

FILE の指定がなかったり, - であった場合, 標準入力から読み込みます.

  -A, --show-all           equivalent to -vET
  -b, --number-nonblank    number nonempty output lines, overrides -n
  -e                       equivalent to -vE
  -E, --show-ends          display $ at end of each line
  -n, --number             number all output lines
  -s, --squeeze-blank      suppress repeated empty output lines
  -t                       -vTと同じ
  -T, --show-tabs          TAB文字を`^I'で表示
  -u                       (無視)
  -v, --show-nonprinting   非表示文字と`^'や`^'を付けて表示 (LFDとTABは除く)
      --help     この使い方を表示して終了する
      --version  バージョン情報を表示して終了する

例:
  cat f - g  最初に f の中身を出力し、次に標準入力を出力します。
            そして g の中身を出力します。
  cat        標準入力を標準出力に複製します。

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report any translation bugs to <https://translationproject.org/team/>
Full documentation <https://www.gnu.org/software/coreutils/cat>
or available locally via: info '(coreutils) cat invocation'
```



### cat実践

複数のファイルを連結して表示と標準入力から読み込みを試します。

以下の5行目と7行目が標準入力で、6行目と8行目が標準入力から読み込んだものを標準出力した結果です。2~4行目はfileAの中身。12~14行目はfileBの中身です。



```
$ cat ./fileA - ./fileA ./fileB
fileA text line1.
fileA text line2.
fileA text line3.
hyojyunnyuryokudayo
hyojyunnyuryokudayo
hyojyunikaryaku
hyojyunikaryaku
fileA text line1.
fileA text line2.
fileA text line3.
fileB text line1.
fileB text line2.
fileB text line3.
```



#### Ctrl + d

ちなみに標準入力の終了は`Ctrl+d`です。`Enter`を入力しても改行されるだけで入力は終わりません。



http://echoes.hak.hokkyodai.ac.jp/db/271/node6.html



## リダイレクト

`cat << EOF > [ファイル名]`の `<<` 、`>`に当たる部分の説明をします。

その前にFDの説明をします。



### FD（File Descriptor）

ファイルを開くと、ファイルテーブルに当該ファイルの情報が記録され、そのファイルの識別番号がファイルディスクリプタ(FD(File Descriptor))です。

ファイルディスクリプタは0から順番に、未使用の最も小さい値が割り振られます。

UNIX系ではファイル以外もファイルとして扱われる。

- 標準入力：キーボードからの入力
- 標準出力：画面への出力
- 標準エラー出力：画面への出力

したがって、上記のようなものにもファイルディスクリプタが割り振られます。

ただし、上記は0～2の値が固定的に与えられることになっています。



| FD   | 略称   | 日本語         | 説明                 |
| ---- | ------ | -------------- | -------------------- |
| 0    | stdin  | 標準入力       | キーボードからの入力 |
| 1    | stdout | 標準出力       | 画面への出力         |
| 2    | stderr | 標準エラー出力 | 画面への出力         |



https://e-words.jp/w/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%82%BF.html



https://wa3.i-3-i.info/word14383.html



### リダイレクト

リダイレクトとは、標準の入出力ではなく、他の入出力に切り替えることである。



| リダイレクト | 説明                                                         |
| ------------ | ------------------------------------------------------------ |
| `>`          | `>`：出力をリダイレクト。上書き。（元のファイルの内容は消える）。<br>`>>`：出力をリダイレクト。追記。（元のファイルの最後に追加で書き加える）。<br>`2>` ：標準エラー出力をリダイレクトする。<br>`>&1`：リダイレクトされた出力を標準出力で受ける。<br>上記を組み合わせると`cat XXXX 2>&1 | tr 'a-z' 'A-Z' `のように標準エラー出力を標準出力にリダイレクトし、その結果をパイプで次のコマンドに渡すという事もできます。 |
| `<`          | `<`：入力をリダイレクト。<br>`<<`：ヒアドキュメント。区切文字列が入力されるまで標準入力する。 |



https://linux.keicode.com/commands/redirect-basics.php



https://linux.keicode.com/commands/pipe-basics.php



https://izumii19.hatenablog.com/entry/2018/11/29/000000



https://www.kushiro-ct.ac.jp/yanagawa/ex-2017/3-unix/03.html



https://qiita.com/kite_999/items/e77fb521fc39454244e7



#### リダイレクト実践



##### 標準出力をファイルにリダイレクト



```
$ cat ./file_a
fileA text line1.
fileA text line2.
fileA text line3.

$ cat ./file_a > ./file_a2

$ cat ./file_a2
fileA text line1.
fileA text line2.
fileA text line3.
```



##### 標準エラー出力をファイルにリダイレクト

まずは失敗例。標準エラー出力のリダイレクトは`2>`コマンドを使うのが正しいです。下記は間違い。

標準出力には何も出力されていないので、それをファイルにリダイレクトしても空のファイルになるだけです。



```
$ ls
error  test.txt

$ cat XXX > error
cat: XXX: No such file or directory

$ cat ./error

```



次は成功例。うまくファイルに出力できました。



```
$ ls
error  test.txt

$ cat XXX 2> error


$ cat ./error
cat: XXX: No such file or directory
```



#####　複雑なリダイレクト

「標準エラー出力 > 標準出力 > パイプ > 次のコマンド(小文字を大文字に変換)」という流れでリダイレクトしています。



```
$ ls
error  test.txt

$ cat XXX 2>&1 | tr a-z A-Z
CAT: XXX: NO SUCH FILE OR DIRECTORY
```



#### ヒアドキュメント

UNIX系におけるヒアドキュメントとはざっくり調べた感じだと以下のような感じです。

- 標準入力である。
- 変数展開などが行える。

印象的には少し便利な標準入力といった感じですね。実際に使ってみるとまた違った印象になるのかもしれません。

（WikipediaによるとC++におけるRaw文字列リテラルの仲間？）



https://ja.wikipedia.org/wiki/%E3%83%92%E3%82%A2%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88



##### ヒアドキュメント実践

ヒアドキュメントで変数展開してみます。

まずは標準入力をファイルに出力してみました。変数名がそのままファイルに出力されており、変数展開されておりません。



```
$ cat - > ./test
$PWD

$ cat ./test
$PWD
```



次にヒアドキュメントをファイルに出力してみました。たしかに変数展開されています。



```
$ cat << EOF > ./test
> $PWD
> EOF

$ cat ./test
/home/[ユーザー名]/cpp/ezoeryou_cpp_intro/sample_002
```



## cat << EOF > [ファイル名] は何をしているのか？

今まで調べた事で本コマンドを説明できるようになりました。



**`cat << EOF > [ファイル名]`の解説**

1. `EOF`という区切り文字まで標準入力（ヒアドキュメント）として受け取る。
2. 受け取った標準入力（ヒアドキュメント）を`cat`で標準出力する。
3. `cat`の標準出力をファイルへの出力にリダイレクト（出力先を切り替え）する。



### cat << EOF > [ファイル名] 実践

`cat << EOF > [ファイル名]`のコマンドを実践してみます。



実行前



```
$ ls
fileA  fileB  
```



catでヒアドキュメントをファイルにリダイレクト＆ファイル作成

（ヒアドキュメント > 標準出力 > リダイレクト > ファイルに出力）



```
$ cat <<EOF > ./fileC
> fileC text line1.
> fileC text line2.
> fileC text line3.
> EOF
```



ファイルが作成されたか確認



```
$ ls
fileA  fileB  fileC 
```



中身の確認



```
$ cat ./fileC
fileC text line1.
fileC text line2.
fileC text line3.
```



実行できました。理解した動作と合っています。