シンボリックリンクを無視するようにBash 4 'globstar'オプションを強制する

シンボリックリンクを無視するようにBash 4 'globstar'オプションを強制する

**Bash 4には、複数のディレクトリにわたってグローブするためのzshの構文をエミュレート(つまり盗む)「globstar」という素晴らしいオプションがあります。しかし、常にシンボリックリンクをたどるので(少なくとも私の使い方では)多少破損します。

**シンボリックリンクをたどるのを防ぐ方法はありますか?そうでない場合は、将来のバージョンでBashにこの機能を追加する予定はありますか?それまで(またはそのような計画がない場合)、誰でも適切な(そして便利な)解決策を提案できますか?

zshの実装がより柔軟で、この問題がないことを読んだようです。しかし、残念ながら、私は仕事で多くのbashスクリプトをソースとして使用し、時間がないか時間がないのでzshに直接切り替えることはできません。すべてzshに変換し、専門知識を最新の状態に保ちます。 (Bashサブシェルを起動し、必要なスクリプトをインポートしてから、変更されたすべての環境変数、エイリアス、関数などを何らかの方法でzshにバックポートすることは可能かもしれませんが、そうする方法もわかりません。)

私はそれを使用して、find私が望む方法で動作する関数を書いてから、関数にエイリアスを追加できることを知ってい**ますが、そのようなことをすることはできませんpath/to/parent/**/child/paths。親パスを最初の引数として使用し、それを設定して実行するコマンドの引数として含む関数のエイリアスです。これは恥ずかしくて醜いことで、本当に良いものが欲しいです。 (特にこの形式は簡単に変形を可能にし、簡単に直感的ですが、関数はそれを別々に合計に変換しますが、2番目は本当に悪いです。)$(** path/to/parent child/paths)**--wholename */child/paths/*findpath/**/pathpath/****/path** path/** '.' /path

どんなアイデアがありますか?

答え1

**それ以降はシンボリックリンクには従いませんbash-4.3

バラより多様性bash-4.3-releasebash-4.3-rc2

globstar(**) は、ディレクトリで解決されるシンボリックリンクを通過しなくなりました。これにより、一部の重複項目が削除されます。

答え2

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よりも速くなるというもう1つの利点があります。

答え3

より簡単な解決策を見つけました。 zshを使用してこれらのグローブを評価するだけです。

私のbash設定スクリプトには次のものがあります。

function zeval () {
    echo $@ | zsh
}
alias z*='zeval echo'

これで、zshを使用するたびに/path/with/**/globbashで次のことができます。

$(z* sandbox/rmall_gdsarc/**/*gds)

エイリアスが拡張されるコンテキストとワイルドカードを必要とするコンテキストは通常​​重複しないため、エイリアスはz*あいまいではありません。

(別名とBash globの構文との間の混乱について私が考えることができる唯一の状況は、すでにパスにあり、z*「z」で始まる実行可能スクリプトを含むディレクトリにあり、globを使用したい場合です...とにかく星の意味ありません)。

関連情報