概要
現在,シェルスクリプトについて勉強しています.些細なことですが,コマンドを個別で実行してリダイレクトさせた場合と,スクリプト化したものを一括で実行してリダイレクトさせた場合とで実行結果が異なっており,もやもやしています.実行結果が異なる理由と私の理解が誤っている点があればご教授いただきたく考えています.
検証内容と結果
コマンドを個別で実行してリダイレクトさせた場合(i)とスクリプト化したものを一括で実行してリダイレクトさせた場合(ii)とでterminalに出力される結果とリダイレクト先のテキストファイルに出力される結果を確認し,比較しました.
コマンドを個別で実行してリダイレクトさせた場合(i)
terminal
1#(i)-(i)echoコマンドの標準出力結果の参照先(ファイルディスクリプタ1)をtest1.txtに変更 2~/testdir$ echo test-std 1>test1.txt 3~/testdir$ cat test1.txt 4test-std 5#(i)-(ii)echoコマンドの標準エラー出力結果の参照先(ファイルディスクリプタ2)をtest2.txtに変更 6~/testdir$ echo test-std 2>test2.txt 7test-std 8~/testdir$ cat test2.txt 9#(i)-(iii)echoコマンドの標準出力結果の参照先(ファイルディスクリプタ1)を標準エラー出力に変更後,ファイルディスクリプタ1の参照先をtest3.txtに変更 10~/testdir$ echo test-err 1>&2 1>test3.txt 11~/testdir$ cat test3.txt 12test-err 13#(i)-(iv)echoコマンドの標準出力結果の参照先(ファイルディスクリプタ1)を標準エラー出力に変更後,ファイルディスクリプタ2の参照先をtest4.txtに変更 14~/testdir$ echo test-err 1>&2 2>test4.txt 15test-err 16~/testdir$ cat test4.txt
上記のそれぞれの検証内容と結果に対して,想定していたファイルディスクリプタの参照先の変化と出力結果は以下の(i)-(i)~(i)-(iv)に示したそれぞれの表の通りです.いずれの結果もファイルディスクリプタが予想通りの参照先を指定しており,かつ予想通りの結果を出力しています.
(i)-(i).
ファイルディスクリプタ | echo実行直後 | 1>test1.txt |
---|---|---|
1 | 標準出力 (出力:test-std) | test1.txt (出力:test-std) |
2 | 標準エラー出力(出力なし) | 標準エラー出力(出力なし) |
出力先 | 予想結果 | テスト結果 |
---|---|---|
terminal | ||
test1.txt | test-std | test-std |
テスト結果ではtest1.txtにtest-stdが出力されており,terminalには何も出力されていないため,上記の予想結果と一致しています.
(i)-(ii).
ファイルディスクリプタ | echo実行直後 | 2>test2.txt |
---|---|---|
1 | 標準出力 (出力:test-std) | 標準出力 (出力:test-std) |
2 | 標準エラー出力(出力なし) | test2.txt(出力なし) |
出力先 | 予想結果 | テスト結果 |
---|---|---|
terminal | test-std | test-std |
test2.txt |
テスト結果ではtest2.txtに何も出力されておらず,terminalにはtest-stdが出力されているため,上記の予想結果と一致しています.
(i)-(iii).
ファイルディスクリプタ | echo実行直後 | 1>&2 | 1>test3.txt |
---|---|---|---|
1 | 標準出力 (出力:test-err) | 標準エラー出力 (出力:test-err) | test3.txt (出力:test-err) |
2 | 標準エラー出力(出力なし) | 標準エラー出力(出力なし) | 標準エラー出力(出力なし) |
出力先 | 予想結果 | テスト結果 |
---|---|---|
terminal | ||
test3.txt | test-err | test-err |
テスト結果ではtest3.txtにはtest-errが出力されており,terminalには何も出力されていないため,上記の予想結果と一致しています.
(i)-(iv).
ファイルディスクリプタ | echo実行直後 | 1>&2 | 2>test4.txt |
---|---|---|---|
1 | 標準出力 (出力:test-err) | 標準エラー出力 (出力:test-err) | 標準エラー出力 (出力:test-err) |
2 | 標準エラー出力(出力なし) | 標準エラー出力(出力なし) | test4.txt(出力なし) |
出力先 | 予想結果 | テスト結果 |
---|---|---|
terminal | test-err | test-err |
test4.txt |
テスト結果ではtest4.txtには何も出力されておらず,terminalにはtest-errが出力されているため,上記の予想結果と一致しています.
スクリプト化したものを一括で実行してリダイレクトさせた場合(ii)
問題は,上記のechoコマンドを一つのスクリプトにまとめ込み,スクリプトを実行させた場合です.スクリプトは以下のとおりです.なお,スクリプト名はtest.shです.
#!/bin/bash echo "test-std" echo "test-err" 1>&2
このスクリプトに対する検証内容と結果を以下に示します.
terminal
1#(ii)-(i)スクリプトの標準出力結果の参照先(ファイルディスクリプタ1)をtest6.txtに変更 2~/testdir$ ./test.sh 1> test6.txt 3test-err 4~/testdir$ cat test6.txt 5test-std 6#(ii)-(ii)スクリプトの標準エラー出力結果の参照先(ファイルディスクリプタ2)をtest5.txtに変更 7~/testdir$ ./test.sh 2> test5.txt 8test-std 9~/testdir$ cat test5.txt 10test-err
上記のそれぞれの検証内容と結果に対して,想定していたファイルディスクリプタの参照先の変化と出力結果は以下の(ii)-(i)と(ii)-(ii)に示したそれぞれの表の通りです.
(ii)-(i).
ファイルディスクリプタ | スクリプト(1行目) | スクリプト(2行目) | スクリプト実行直後 | 1>test6.txt |
---|---|---|---|---|
1 | 標準出力 (出力:test-std) | 標準エラー出力 (出力:test-err) | 標準出力(出力:test-std)と標準エラー出力(出力:test-err) | test6.txt (出力:test-stdとtest-err) |
2 | 標準エラー出力(出力なし) | 標準エラー出力(出力なし) | 標準エラー出力(出力なし) | 標準エラー出力(出力なし) |
出力先 | 予想結果 | テスト結果 |
---|---|---|
terminal | test-err | |
test6.txt | test-stdとtest-err | test-std |
テスト結果と比較すると,テスト結果ではtest6.txtにtest-stdのみが出力されており,terminalにはtest-errが出力されています.
(ii)-(ii).
ファイルディスクリプタ | スクリプト実行中(1行目) | スクリプト実行中(2行目) | スクリプト実行直後 | 2>test5.txt |
---|---|---|---|---|
1 | 標準出力 (出力:test-std) | 標準エラー出力 (出力:test-err) | 標準出力(出力:test-std)と標準エラー出力(出力:test-err) | 標準出力(出力:test-std)と標準エラー出力(出力:test-err) |
2 | 標準エラー出力(出力なし) | 標準エラー出力(出力なし) | 標準エラー出力(出力なし) | test5.txt (出力なし) |
出力先 | 予想結果 | テスト結果 |
---|---|---|
terminal | test-stdとtest-err | test-std |
test5.txt | test-err |
テスト結果と比較すると,テスト結果ではtest5.txtにtest-errのみが出力されており,terminalにはtest-stdが出力されています.
いずれの結果も出力結果test-errの参照先が予想とテスト結果で異なっており,スクリプト実行直後にファイルディスクリプタ2の参照先となっていれば,予想とテスト結果が合致すると言えます.そこでスクリプト2行目の動作を見直してみると,echoでstd-errを標準出力として出力した後に(std-errのファイルディスクリプタは1),1>&2の操作によって,ファイルディスクリプタ1の参照先を標準出力エラーとしているため,やはり標準出力エラーとしてstd-err(ファイルディスクリプタは1)が出力されると予想されます.また,コマンドを個別で実行してリダイレクトさせた場合(i)ではそのように動作していることから,恐らくこの理解で問題がないと予想されます.
質問事項
以上のようにコマンドを個別で実行してリダイレクトさせた場合と,スクリプト化したものを一括で実行してリダイレクトさせた場合とで異なる実行結果が得られています.そこで,以下の2点をご教授いただきたいです.
-
なぜこうなるのでしょうか.
例えば,スクリプトで一括で実行してリダイレクトする場合と,個別で実行してリダイレクトする場合とで,途中の処理が異なるのでしょうか. -
コマンドの実行からリダイレクトについて,上記の理解であっているのでしょうか.もし,間違っている箇所があれば,ご教授いただきたいです.
宜しくお願いいたします.
補足情報(実行環境)
Ubuntu 20.04.2 LTS
デフォルトシェル /bin/bash
回答1件
あなたの回答
tips
プレビュー