ファイル名と取り扱いとコマンド置換
ななし 『ファイルがないと * のままになるので、ls DIR 2>/dev/null と書いたりしますね。』 (2007/07/09 11:10)
まぁ、そのとおりなんだけど、ls とコマンド置換を使ってファイル名を取得しようとすると、パスに空白が含まれていたりする場合にはまれる。
% touch 'odz buffer' % ls `ls` ls: odz: No such file or directory ls: buffer: No such file or directory
あと、関係ないけど、-F オプション付きの GNU ls の挙動はなんだかよくわからない。
% ln -s usr . % ls -F usr usr@ % ls -F usr/ X11R6/ bin/ doc/ games/ include/ lib/ lib64/ local/ sbin/ share/ src/ % ls -F -H usr X11R6/ bin/ doc/ games/ include/ lib/ lib64/ local/ sbin/ share/ src/
で、調べてみたら bash/zsh では nullglob オプションなんてのが存在するので、それを使えばいい。
bash のデフォルトでは、glob にマッチするパスが見つからない場合はパス展開が行われず、zsh のデフォルトではエラーになるのだけど、両方ともに nullglob をセットするとで空に展開されるようになる。
bash の場合は
shopt -s nullglob
zsh の場合は
setopt nullglob
とする。
これをつかって、件の for_all を書き換えればこうなる*1。
#!/bin/bash shopt -s nullglob function rec { local dir="$1" shift for file in "$dir/"*; do if [ -f "$file" ]; then "$@" "$file" elif [ -d "$file" ]; then rec "$file" "$@" fi done } rec "$@"
ちなみに、
#!/bin/bash function rec { local dir="$1" shift ls "$dir" | while read file; do local path="$dir/$file" if [ -f "$path" ]; then "$@" "$path" elif [ -d "$path" ]; then rec "$path" "$@" fi done } rec "$@"
というネタも思いついたけど、やってみたらパス名に改行を含むことができるらしいので没。
*1:パラメータのとり方があれなのでパラメータの順序を勝手に変更してある