bash 的源工作方式与 zsh 的工作方式不同,无法按预期转发源命令

Kal*_*lec 5 bash zsh configuration

我在工作中使用 bash,在家里使用 zsh,不同的 macbook。我对 bash 或 zsh 脚本知之甚少,所以我不敢进行切换,直到我设法让我的 ZSH 与我工作时的水平相当,这样我就不会失去生产力。

我最终.dot-files在 github 上创建了一个存储库,并想测试所有内容。有效。但当我决定进行最后一次调整时,一切都崩溃了,我一生都无法理解为什么。

设想:

我将 ~/.dot-files 作为我的 git 存储库的根目录。然后是两个子文件夹,zsh以及bash. 在每个文件里面我都有隐藏的文件,以及一个想要获取它们的配置。

$ cd ~/.dot-files/bash/
$ ls -la
drwxr-xr-x  8 me  staff    256 May  8 13:28 .
drwxr-xr-x  7 me  staff    224 May  8 13:00 ..
-rw-r--r--  1 me  staff   1791 May  8 13:08 .alias
-rw-r--r--  1 me  staff  79837 Apr 12  2022 .git-completion.bash
-rw-r--r--  1 me  staff   1602 May  8 13:49 .git-prompt
-rw-r--r--  1 me  staff   1816 May  8 13:06 .ps1
-rw-r--r--  1 me  staff    877 May  8 13:09 .utils
-rw-r--r--  1 me  staff    142 May  8 15:20 default-config
Run Code Online (Sandbox Code Playgroud)

$ cd ~/.dot-files/zsh/
$ ls -la
drwxr-xr-x  7 me  staff    224 May  8 13:33 .
drwxr-xr-x  7 me  staff    224 May  8 13:00 ..
-rw-r--r--  1 me  staff   1423 May  8 12:32 .alias
-rw-r--r--  1 me  staff  18582 May  8 12:32 .git-prompt.sh
-rw-r--r--  1 me  staff   2059 May  8 12:32 .prompt
-rw-r--r--  1 me  staff    926 May  8 14:01 .zsh-git-info
-rw-r--r--  1 me  staff    143 May  8 15:02 default-config
Run Code Online (Sandbox Code Playgroud)

$ 猫 ~/.bashrc

$ cd ~/.dot-files/bash/
$ ls -la
drwxr-xr-x  8 me  staff    256 May  8 13:28 .
drwxr-xr-x  7 me  staff    224 May  8 13:00 ..
-rw-r--r--  1 me  staff   1791 May  8 13:08 .alias
-rw-r--r--  1 me  staff  79837 Apr 12  2022 .git-completion.bash
-rw-r--r--  1 me  staff   1602 May  8 13:49 .git-prompt
-rw-r--r--  1 me  staff   1816 May  8 13:06 .ps1
-rw-r--r--  1 me  staff    877 May  8 13:09 .utils
-rw-r--r--  1 me  staff    142 May  8 15:20 default-config
Run Code Online (Sandbox Code Playgroud)

$ cat ~/.dot-files/bash/default-config

$ cd ~/.dot-files/zsh/
$ ls -la
drwxr-xr-x  7 me  staff    224 May  8 13:33 .
drwxr-xr-x  7 me  staff    224 May  8 13:00 ..
-rw-r--r--  1 me  staff   1423 May  8 12:32 .alias
-rw-r--r--  1 me  staff  18582 May  8 12:32 .git-prompt.sh
-rw-r--r--  1 me  staff   2059 May  8 12:32 .prompt
-rw-r--r--  1 me  staff    926 May  8 14:01 .zsh-git-info
-rw-r--r--  1 me  staff    143 May  8 15:02 default-config
Run Code Online (Sandbox Code Playgroud)

这不起作用

-bash: ./.git-prompt: No such file or directory
-bash: ./.ps1: No such file or directory
-bash: ./.alias: No such file or directory
-bash: ./.utils: No such file or directory
Run Code Online (Sandbox Code Playgroud)

$ 猫 ~/.zshrc

source ~/.dot-files/bash/default-config
Run Code Online (Sandbox Code Playgroud)

$ cat ~/.dot-files/zsh/default-config

source "$(dirname -- "$0")/.git-prompt"
source "$(dirname -- "$0")/.ps1"
source "$(dirname -- "$0")/.alias"
source "$(dirname -- "$0")/.utils"
Run Code Online (Sandbox Code Playgroud)

这确实有效,完美。

我正在尝试做什么

我想改变我的外壳chsh -s /bin/bash,重新启动终端。我希望它能发挥作用。

~/.bashrc想将它指向一个任何人都可以在任何地方克隆的存储库。

我希望该存储库引用默认配置所在位置的相对路径。我不想有硬编码的完整路径。

对于 zsh 来说,source "$(dirname "$0")就可以了。据我了解,步骤如下:

  • ~/.zshrc直接调用文件的源:~/.dot-files/zsh/default-config
  • 所述文件调用源命令,是的,但它插入“我的路径”,后跟$(dirname "$0")与“我”位于同一文件夹中的文件名。
    • source "$(dirname "$0")/.alias"转变为source ~/.dot-files/zsh/.alias

Bash 不起作用,不知道为什么。

Gil*_*il' 6

在 Bourne/POSIX shell 中,特殊参数$0设置为 shell 执行的脚本的名称(或 shell 本身的名称)。.使用(\xe2\x80\x9cdot\xe2\x80\x9d)命令读取另一个脚本文件时它不会改变。Bash在这方面遵循标准行为,包括使用(\xe2\x80\x9cdot\xe2\x80\x9d)source的同义词时。.

\n

在 zsh 中,默认情况下,特殊参数$0设置为当前脚本的路径或当前函数的名称,即,当使用.source内置函数、调用函数以及从函数或脚本返回时,它会发生变化。function_argzero您可以通过取消设置该选项(除非 zsh 处于 sh 或 ksh 模拟模式,否则默认设置)或设置 来将zsh 更改为标准行为posix_argzero

\n

在 bash 中,当前脚本的路径(受.或影响source)在名称下可用$BASH_ARGV0

\n
\n

顺便说一句,由于您知道有一个带有目录组件的非目录文件的路径,因此您可以使用简单且稍快的方式"${0%/*}"来引用包含该文件的目录。1

\n

1它也比"$(dirname -- "$0")"目录名称以换行符结尾时更有效,以及"$(dirname "$0")"路径以破折号开头时更有效,但这些都不适用于此。它更脆弱,因为如果路径以斜杠结尾或根本不包含斜杠,它就不起作用,但这也不适用于此。

\n


Whi*_*Owl 3

有两种简单的方法可以解决您的问题:

使用pushd/popd

只需更改文件中的当前文件夹default-config并随后恢复:

if pushd ~/.dot-files/bash/ > /dev/null; then
  source ./.alias
  source ./.prompt
  source ./.zsh-git-info
  source ./.git-prompt.sh
  popd > /dev/null
fi
Run Code Online (Sandbox Code Playgroud)

(在 zsh 中,您可以使用-q而不是将 stdout 重定向到 /dev/null 来避免目录堆栈的转储,但在 bash 中则不行)。

当然,您的default-config文件在这一行中会有所不同。

使用变量

.bashrc在和内定义一个变量.zshrc。该变量将指向源文件所在的位置:

# .bashrc
fdir=~/.dot-files/bash
source "${fdir}/default-config"
Run Code Online (Sandbox Code Playgroud)

做同样的事.zshrc

两个 shell 的内部default-config可以相同,只需重用此变量即可:

source "${fdir}/.alias"
source "${fdir}/.prompt"
source "${fdir}/.zsh-git-info"
source "${fdir}/.git-prompt.sh"
Run Code Online (Sandbox Code Playgroud)