前置き
最近使用したcat << EOF > [ファイル名]
というコマンドについて調べてみた。
catコマンド
cat << EOF > [ファイル名]
のcat
に当たる部分の説明をします。
書式
cat [,オプション/]... [,ファイル/]...
機能説明
ファイル (複数可) の内容を結合して標準出力に出力します。
ファイルの指定がない場合や FILE が - の場合, 標準入力から読み込みを行います。
ファイルを連結して表示できるなんて知らなかった。標準入力から読み込みなんてもっと知らなかった。
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
を入力しても改行されるだけで入力は終わりません。
リダイレクト
cat << EOF > [ファイル名]
の <<
、>
に当たる部分の説明をします。
その前にFDの説明をします。
FD(File Descriptor)
ファイルを開くと、ファイルテーブルに当該ファイルの情報が記録され、そのファイルの識別番号がファイルディスクリプタ(FD(File Descriptor))です。
ファイルディスクリプタは0から順番に、未使用の最も小さい値が割り振られます。
UNIX系ではファイル以外もファイルとして扱われる。
- 標準入力:キーボードからの入力
- 標準出力:画面への出力
- 標準エラー出力:画面への出力
したがって、上記のようなものにもファイルディスクリプタが割り振られます。
ただし、上記は0~2の値が固定的に与えられることになっています。
FD | 略称 | 日本語 | 説明 |
---|---|---|---|
0 | stdin | 標準入力 | キーボードからの入力 |
1 | stdout | 標準出力 | 画面への出力 |
2 | stderr | 標準エラー出力 | 画面への出力 |
リダイレクト
リダイレクトとは、標準の入出力ではなく、他の入出力に切り替えることである。
リダイレクト | 説明 |
---|---|
> |
> :出力をリダイレクト。上書き。(元のファイルの内容は消える)。>> :出力をリダイレクト。追記。(元のファイルの最後に追加で書き加える)。2> :標準エラー出力をリダイレクトする。>&1 :リダイレクトされた出力を標準出力で受ける。上記を組み合わせると`cat XXXX 2>&1 |
< |
< :入力をリダイレクト。<< :ヒアドキュメント。区切文字列が入力されるまで標準入力する。 |
リダイレクト実践
標準出力をファイルにリダイレクト
$ 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文字列リテラルの仲間?)
ヒアドキュメント実践
ヒアドキュメントで変数展開してみます。
まずは標準入力をファイルに出力してみました。変数名がそのままファイルに出力されており、変数展開されておりません。
$ cat - > ./test
$PWD
$ cat ./test
$PWD
次にヒアドキュメントをファイルに出力してみました。たしかに変数展開されています。
$ cat << EOF > ./test
> $PWD
> EOF
$ cat ./test
/home/[ユーザー名]/cpp/ezoeryou_cpp_intro/sample_002
cat << EOF > [ファイル名] は何をしているのか?
今まで調べた事で本コマンドを説明できるようになりました。
cat << EOF > [ファイル名]
の解説
-
EOF
という区切り文字まで標準入力(ヒアドキュメント)として受け取る。 - 受け取った標準入力(ヒアドキュメント)を
cat
で標準出力する。 -
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.
実行できました。理解した動作と合っています。