全力で怠けたい

怠けるために全力を尽くしたいブログ。

シェルのリダイレクトでわりと使うやつのメモ。

シェルのリダイレクトでわりと使うやつをメモしておく。

シェルのリダイレクト

シェルスクリプトを書くときにわりと使うリダイレクトのやつを書いていく。

/bin/sh のバージョン。普通に bash.

$ /bin/sh --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin19)
Copyright (C) 2007 Free Software Foundation, Inc.

このへんは man sh すると sh は /private/var/select/shシンボリックリンクが実行すると書いてあるので /private/var/select/sh を見たら /bin/bash へのシンボリックリンクになってた。 /bin/sh を実行すると /bin/bash が sh 互換で動く感じ。

It is implemented by re-execing as either bash(1), dash(1), or zsh(1) as determined by the symbolic link located at /private/var/select/sh.

標準出力のリダイレクト

標準出力のリダレクトは > を使う。

# 標準出力をファイルにリダイレクトする
$ echo Hello > stdout.txt
$ cat stdout.txt
Hello

> はリダイレクト先のファイルの中身を上書きする。

$ echo Hello > stdout.txt
$ echo World > stdout.txt
$ cat stdout.txt
World

リダイレクト先のファイルを上書きじゃなくて追記するときは >> を使う。

$ echo Hello > stdout.txt
$ echo World >> stdout.txt
$ cat stdout.txt
Hello
World

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

標準エラー出力> でリダイレクトするけど >標準エラー出力はリダイレクトしない。 ls /hoge/not/exists みたいに存在しないファイルを ls するとメッセージがプロンプトに表示するしリダイレクト先の stderr.txt は空っぽになる。

$ ls /hoge/not/exists
ls: /hoge/not/exists: No such file or directory
$ cat stderr.txt

標準エラー出力のリダイレクトは 2> を使う。 ls /hoge/not/exists みたいに存在しないファイルを ls するとメッセージがプロンプトに表示されなくてちゃんとリダイレクト先の stderr.txt に入る。

$ ls /hoge/not/exists 2> stderr.txt

$ cat stderr.txt
ls: /hoge/not/exists: No such file or directory

2> はリダイレクト先のファイルを上書きする。リダイレクト先のファイルを上書きじゃなくて追記するときは 2>> を使う。

$ ls /hoge/not/exists 2> stderr.txt
$ ls /fuga/not/exists 2> stderr.txt
$ cat stderr.txt
ls: /fuga/not/exists: No such file or directory

$ ls /hoge/not/exists 2> stderr.txt
$ ls /fuga/not/exists 2>> stderr.txt
$ cat stderr.txt
ls: /hoge/not/exists: No such file or directory
ls: /fuga/not/exists: No such file or directory

標準入力とかのリダイレクトで使うファイルディスクリプタ

標準エラーのリダイレクトで 2> とか 2>> みたいにしたときの 2 はファイルディスクリプタを指定してる。

標準出力とか標準エラー出力のファイルディスクリプタは一般的に以下のようになってるので 2>標準エラー出力をリダイレクトするという意味になる。

ファイルディスクリプタ 対象
0 標準入力
1 標準出力
2 標準エラー出力

あと標準出力のリダイレクトは > とか >> みたいに書いたけど標準出力のファイルディスクリプタ1 なので 1> とか 1>> みたいにしても同じ動きになる。

$ echo Hello 1> stdout.txt
$ echo World 1>> stdout.txt
$ cat stdout.txt
Hello
World

標準入力のリダイレクト

標準入力のリダレクトは < を使う。

$ cat stdout.txt
Hello
World

$ grep Hello < stdout.txt
Hello

ヒアドキュメント

標準入力はヒアドキュメント << をリダイレクトすることができる。

$ cat << EOF
Hello
World
EOF
Hello
World

$ grep Hello << EOF
Hello
World
EOF
Hello

標準出力をファイルにリダイレクトして空っぽのファイルを作る

ファイルを空っぽにするときに echo > stdout.txt みたいにすると stdout.txt の内容は空っぽにならない。

$ echo > stdout.txt
$ ls -l stdout.txt
-rw-r--r--  1 shrimp  staff  1  7 24 14:48 stdout.txt

$ od stdout.txt
0000000    000012
0000001

これ、bash なら echo -n > stdout.txt でファイルを空っぽにできるけど sh で echo -n > stdout.txt をやると -n というファイルになっちゃう。

rm stdout.txt; touch stdout.txt でファイルを削除してから空のファイルを作ってもいいけど :> みたいにするほうが楽なので :> を使うことが多い気がする。

$ :> stdout.txt
$ ls -l stdout.txt
-rw-r--r--  1 shrimp  staff  0  7 24 14:49 stdout.txt

$ od stdout.txt

ちなみに ubuntu/bin/sh が dash のシンボリックリンクになってるんだけど echo -n > stdout.txt で普通にファイルを空っぽに出来ると Twitter で教えてもらった。

docker container run --rm -it ubuntu /bin/sh コマンドで ubuntu の Docker コンテナを起動していろいろ試してみたけどちゃんと echo -n > stdout.txt でファイルを空っぽにできる……

# ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Aug  7  2019 /bin/sh -> dash

# echo -n > stdout.txt
# ls -l stdout.txt
-rw-r--r-- 1 root root 0 Jul 24 10:31 stdout.txt

# cat stdout.txt

参考サイト