Bash 4には、複数のディレクトリ間でグロブするためのzshの**
構文をエミュレートする(つまり、盗まれた)「globstar」と呼ばれる素晴らしいオプションがあります。ただし、常にシンボリックリンクをたどるという事実により、(少なくとも私の使用法では)多少不自由になっています。
**
がシンボリックリンクをたどらないようにする方法はありますか?そうでない場合、将来のリリースでこの機能をBashに追加する予定はありますか?それまで(またはそのような計画がない場合)、誰かがまともな(そして便利な)回避策を提案できますか?
Zshの実装はより柔軟で、この問題はないことを読んだと思いますが、残念ながら、職場で多くのbashスクリプトを調達しているため、zshに切り替えることができず、時間がありません。または、それらすべてをzshに変換し、最新の状態に保つためのノウハウ。 (Bashサブシェルを開始し、目的のスクリプトを入手してから、変更されたすべてのenv変数、エイリアス、関数などをzshにバックポートすることは可能かもしれないと思いますが、その方法もわかりません。)
find
を使用して、希望どおりに動作する関数を記述し、**
をこの関数にエイリアスできることはわかっていますが、path/to/parent/**/child/paths
のようなことを実行できず、正しく機能しません。最も近いのは$(** path/to/parent child/paths)
のようなものです。ここで、**
は、親パスを最初の引数として取り、--wholename */child/paths/*
をfind
コマンドの引数として含む関数にエイリアスされます。構築して実行します。これは厄介で醜いです、そして私は本当にもっと良いものが欲しいです。 (特に、path/**/path
形式でpath/**
と**/path
のバリエーションを簡単かつ直感的に簡単に許可できるのに対し、関数はこれをそれぞれ** path/
と** '.' /path
に変換し、2番目はひどいものになるのが好きです。)
何かご意見は?
**
は、bash-4.3
以降、シンボリックリンクをたどりません。
[〜#〜] change [〜#〜]bash-4.3-release
とbash-4.3-rc2
の間を参照してください。
globstar(**)は、ディレクトリに解決されるシンボリックリンクをトラバースしなくなりました。これにより、一部の重複エントリが排除されます。
**
がbashでシンボリックリンクをたどるのを防ぐ方法はありません。また、 方法を提供する要求 応答もありません。
コードを記述したい場合は、bashにパッチを適用して、**
でシンボリックリンクトラバーサルをオフにする新しいオプションを導入できます。パッチをbashメンテナに送信すると、その機能がいつか存在する可能性が高くなります。それでも、少なくとも当面の間は、重要なシステムプログラムのローカルバージョンを展開して維持する必要がありますが、これはおそらく悪い考えです。
エイリアスを使用して**
の動作を変更する方法はありません。中間配列を使用して展開の結果を格納する場合、代わりにfind
を使用する方法は次のとおりです。
find . … -print0 | {
a=()
while read -r -d "" line; do
a+=("$line")
done
frobnicate "${a[@]}"
}
Bashはサブプロセスでパイプラインの右側を実行するため、find
の出力を使用するプログラム全体がパイプラインの右側にある必要があることに注意してください。
名前に改行文字が含まれているファイルを除外しても問題がない場合は、次の方が簡単です。
set -f; IFS=
a=($(find . … ! -name $'*\n*' -print))
set +f; unset IFS
frobnicate "${a[@]}"
既存のスクリプトをzshのkshエミュレーションモードで実行してみることができます。 Zshはbashのすべての機能を実装しているわけではありません。bashの機能のほとんどすべてがzshに存在しますが、構文に互換性がない場合もあります。スクリプトをksh93で実行することもできます。93o+以降のバージョンはzshのように**
をサポートし、bashの機能のほとんど(すべてではありません)はkshからのものであるため、スクリプトをksh93に簡単に移植できます。 kshに切り替えると、bashやzshよりも高速になる傾向があるという追加の利点があります。