在 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

pushd如果当前位置已经相同,zsh 似乎会忽略该行,因此popd命令会转到$OLDPWD脚本来源之前的位置。

有没有办法阻止 zsh 忽略“冗余”pushd命令,同时保持脚本与 bash 兼容?

我的 中确实有以下内容.zshrc,但当我取消设置它们时也会发生这种情况:

setopt AUTO_PUSHD PUSHD_SILENT PUSHD_IGNORE_DUPS

答案1

pushd旨在popd方便交互。它们在脚本中既不可靠也不有用。

你看到的效果是pushd_ignore_dups,默认情况下关闭,但您显然已在配置中启用。

pushd和的另一个潜在问题popd是您需要确保确实成对调用它们。popd在错误路径上意外省略 a 的风险很高,这会导致到处混乱。

在要获取的辅助脚本中,通常根本不应该更改当前目录。只需在各处使用绝对路径即可。

如果您确实想更改当前目录,请使用该cd命令。将旧的当前目录保存在变量中。

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

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

这适用于所有 Bourne 风格的 shell(甚至是那些没有实现pushdand 的shell popd),并且永远不会恢复错误的目录。

但是,任何基于退出目录并返回目录的代码都会在一种异常情况下中断:如果您无权更改回原始目录。当进程失去权限后,可能会发生这种情况。

答案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符合
  • 阅读吉尔斯的回答

答案3

我已经尝试过这个,这似乎有效,但我想知道其他更好的方法,因为它看起来非常可怕:

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

# Do various things

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

更新不,这实际上不起作用,因为终端在~/.dotfiles目录中时会关闭。

相关内容