バッチ作成時に遭遇した事象についてメモ。
実施環境:
[testuser@testhost ~]$ uname -a
Linux testhost 4.18.0-147.8.1.el8_1.x86_64 #1 SMP Thu Apr 9 13:49:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[testuser@testhost ~]$ echo $SHELL
/bin/bash
バッチ作成時に遭遇した現象
bashのlsコマンドでは、ワイルドカードでファイルを指定した時にヒットするファイルが多すぎると、エラーを起こすことがあります。
[testuser@testhost ~]$ ls *
bash: /usr/bin/ls: Argument list too long
ファイルが大量にある場合に対応できる方法はないかと思い調べると、echoコマンドを使うとよいという話を見ました。
[testuser@testhost ~]$ echo *
test0.log test10000.log test10001.log ...
さてこれを使用しようと考えバッチを作成するも、試験するとなぜか「Argument list too long」が...
原因
原因は、スクリプト内でechoコマンドを「フルパスで」指定していることでした。
[testuser@testhost ~]$ which echo
/usr/bin/echo
[testuser@testhost ~]$ /usr/bin/echo *
bash: /usr/bin/echo: Argument list too long
このように、echoコマンドをフルパスで指定すると、フルパスで指定しない場合と異なる動作をします。
原因をいろいろ調べたのですが、結論から言うとechoコマンドは「2つ」あるようです。
[testuser@testhost ~]$ PATH=
[testuser@testhost ~]$ echo $PATH
[testuser@testhost ~]$ ls *
bash: ls: No such file or directory
上の操作では、変数「PATH」の値を空にして、コマンドのパスを辿れなくしています。
そのため、lsコマンドは見つからず、「そんなコマンドはない」とエラーを出しています。
にも関わらず、echoコマンドは通常通り動作しています。
もしこのechoコマンドが「/usr/bin/echo」なら、echoコマンドも見つからないはずです。
実はこのechoコマンドは、exitやlet等と同じ、「bashの組み込みコマンド」です。
bashの内部に存在するコマンドのため、パスが辿れなくても使用できます。
また、/usr/bin/echoのように引数が多すぎてエラーを起こすことも以下の通りありません。
[testuser@testhost ~]$ echo `echo *`
test0.log test10000.log test10001.log ...
以上、echoコマンドにまつわるちょっとした話でした。