zshからスクリプトをインポートすると、Pushd / popdの動作が混乱する

zshからスクリプトをインポートすると、Pushd / popdの動作が混乱する

bashからインポートされたスクリプトがあります。それはすべての種類のタスクを実行し、$PWD購入する前の状態を維持します。

pushd ~/.dotfiles >/dev/null || exit 1

# Do various things

popd >/dev/null || exit 1

スクリプトはzshでも(ほとんど)うまく機能しますが、その~/.dotfiles場所からインポートしたときにインポートした後、以前の場所に移動します$OLDPWD

pushdzsh は、現在の位置がすでに同じ場合はその行を無視しているように見えるため、popdコマンドは$OLDPWDスクリプトソースの前の位置に移動します。

pushdスクリプトをbashと互換性のあるままにしながら、zshが「冗長」コマンドを無視するのを防ぐ方法はありますか?

私のファイルには次のものがありますが、.zshrc設定を解除してもこの現象が発生します。

setopt AUTO_PUSHD PUSHD_SILENT PUSHD_IGNORE_DUPS

答え1

pushd相互作用を促進するように設計されていますpopd。スクリプトでは信頼できず、便利ではありません。

あなたが見る効果はpushd_ignore_dups、これはデフォルトではオフになっていますが、設定で有効になっているようです。

pushdandのもう1つの潜在的な問題は、popd実際にペアで呼び出す必要があることです。popd誤ったパスから誤ってaを省略すると、あちこちで混乱を引き起こす危険性が高くなります。

インポートするヘルパースクリプトでは通常、現在のディレクトリをまったく変更しないでください。どこでも絶対パスを使用してください。

現在のディレクトリを本当に変更するには、このcdコマンドを使用します。以前の現在のディレクトリを変数に保存します。

# instead of pushd...
foo_old_pwd=$PWD
cd /foo/directory

# instead of popd...
cd "$foo_old"

pushdこれはすべてのBourneスタイルのシェル(および実装されていないシェルを含むpopd)で機能し、無効なディレクトリは決して復元されません。

ただし、ディレクトリを終了してそのディレクトリに戻ることに基づいているすべてのコードは、1つの例外、つまり元のディレクトリに戻す権限がない場合は中断されます。これは、プロセスが権限を失ったときに発生する可能性があります。

答え2

if-then-else現実から出てくる答えが必要です。

if [ $PWD == ~/.dotfiles ] 
then nopopd=true
else pushd ~/.dotfiles >/dev/null || exit 1
fi

# Do various things

[[ ! $nopopd == true ]] && popd >/dev/null || exit 1

参考にしてください

  • これはテストされていません
  • それでも必要か条件(||)がpushd満たされているかわからない
  • Gilesの回答を読む

答え3

私はこれを試してみましたが、これはうまくいくようですが、かなり怖いように見えるので、他のより良い方法を知りたいです。

[[ $PWD == ~/.dotfiles ]] && nopopd=true
pushd ~/.dotfiles >/dev/null || exit 1

# Do various things

[[ ! $nopopd == true ]] && popd >/dev/null || exit 1

修正する~/.dotfilesいいえ、ディレクトリ内に端末が閉じているため、実際には機能しません。

関連情報