【问题标题】:source all files in a directory from .bash_profile从 .bash_profile 获取目录中的所有文件
【发布时间】:2010-11-28 05:51:43
【问题描述】:

我需要允许多个应用程序附加到系统变量(在本例中为 $PYTHONPATH)。我正在考虑指定一个目录,每个应用程序都可以在其中添加一个模块(例如 .bash_profile_modulename)。在 ~/.bash_profile 中尝试过这样的事情:

find /home/mike/ -name ".bash_profile_*" | while read FILE; do
source "$FILE"
done;

但它似乎不起作用。

【问题讨论】:

  • 一个快速测试脚本适合我。您能否更具体地说明您的文件包含什么以及“似乎不起作用”是什么意思?
  • 文件看起来像: export PYTHONPATH=/testpath/:$PYTHONPATH 问题是它没有将 /testpath/ 添加到 PYTHONPATH。
  • 只是为了解释为什么原始脚本不起作用:文件来源于管道中的while循环;管道中使用的 bash 内置函数在子 shell 中执行,因此当子 shell 退出时,源文件定义的任何内容都会消失。解决方案(如下面的答案)是消除管道。
  • 非常类似于这个问题:stackoverflow.com/q/20796200/1695680
  • 这对我来说“似乎不起作用”,但它起作用了。我的一个完成脚本被破坏并且正在撤消早期的工作。所以这是要检查的东西。具体来说,集线器命令的 bash 完成覆盖了 git,并且不适用于最新的 git 版本。

标签: bash shell scripting


【解决方案1】:

不会

 for f in ~/.bash_profile_*; do source $f; done

够了吗?

编辑ls ~/.bash_* 的额外层简化为直接 bash 通配符。

【讨论】:

  • for f in ~/.bash_profile_*;做源 $f; done 也应该有效; bash 可以处理通配符。
  • 这是处理 homebrew 的 /etc 文件夹的超级方法,其中包含托管包的 bash 完成
  • 我有更好的解决方案,适用于不同的外壳,如果没有匹配模式的文件也不会出错:stackoverflow.com/a/42986004/99834
  • 然后你可以使用unset f 来摆脱这个f 变量。
  • 我不知道为什么,但这对我不起作用。这个作品>serverfault.com/a/41524/355902
【解决方案2】:

Oneliner(仅适用于 bash/zsh):

source <(cat *)

【讨论】:

  • 这不适用于 Bash。你得到一个错误“名称”:是一个目录
  • @BalajiBoggaramRamanarayan 如果你有目录的话!问题是关于文件的。查找仅包含文件的掩码。
  • 这不是将它们作为一个脚本一起运行吗?这似乎会产生意想不到的后果。
  • @mckeed 鉴于 source 无论如何都会在同一个 shell 中执行给定的文件,运行单个 source 语句或在连接文件上运行单个语句之间应该没有区别。但是,如果某些文件不以换行符结尾,则此处可能会出现问题。因此,尽管这是一个可爱的代码高尔夫示例,但它并不是 100% 可靠的。
【解决方案3】:

我同意上述丹尼斯的观点;您的解决方案应该可以工作(尽管“完成”后的分号不是必需的)。但是,您也可以使用 for 循环

for f in /path/to/dir*; do
   . $f
done

ls 的命令替换不是必需的,如 Dirk 的回答。这是在 /etc/bash_completion 中使用的机制,用于在 /etc/bash_completion.d 中获取其他 bash 完成脚本

【讨论】:

  • 我相信你需要报价。 . "$f"。除此之外,最佳答案。
  • 我发现在指定目录(即/path/to/dir/*)之后需要一个额外的斜杠。
【解决方案4】:
for file in "$(find . -maxdepth 1 -name '*.sh' -print -quit)"; do source $file; done

到目前为止,这个解决方案是我发现的最可发布的:

  • 如果没有匹配的文件,它不会给出任何错误
  • 适用于多个 shell,包括 bash、zsh
  • 跨平台(Linux、MacOS、...)

【讨论】:

  • 不适用于长文件名或长连接列表
  • 添加-type f以确保文件是文件而不是名为foo.sh的目录!
  • @mazunki 如果添加 -type 选项并且文件夹为空,则会引发“参数不足”错误。如果不添加 -type 选项,则不会像 sorin 在原始帖子中描述的那样抛出错误。
【解决方案5】:

您可以使用此功能来获取目录中的所有文件(如果有):

source_files_in() {
    local dir="$1"

    if [[ -d "$dir" && -r "$dir" && -x "$dir" ]]; then
        for file in "$dir"/*; do
           [[ -f "$file" && -r "$file" ]] && . "$file"
        done
    fi
}

额外的文件检查处理由于目录为空而导致模式不匹配的极端情况(这使得循环变量扩展为模式字符串本身)。

【讨论】:

    【解决方案6】:
    str="$(find . -type f -name '*.sh' -print)"
    arr=( $str )
    for f in "${arr[@]}"; do
       [[ -f $f ]] && . $f --source-only || echo "$f not found"
    done 
    

    我测试了这个脚本并且我正在使用它。 只需修改 .找到后用你的脚本指向你的文件夹,它会起作用。

    【讨论】:

      【解决方案7】:

      好吧,我最终做了什么;

      eval "$(find perf-tests/ -type f -iname "*.test" | while read af; do echo "source $af"; done)"
      

      这将在当前 shell 中执行一个源并维护所有变量...

      【讨论】:

        【解决方案8】:

        我认为你应该能够做到

        source ~/.bash_profile_*

        【讨论】:

        • 我也有同样的想法,但我测试过,无法让它工作。在我看来source 只接受一个论点(并忽略多余的论点)。我很确定这很糟糕。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-14
        • 1970-01-01
        • 2018-07-04
        • 2017-08-20
        • 1970-01-01
        • 2010-12-01
        相关资源
        最近更新 更多