AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 685814
Accepted
php_nub_qq
php_nub_qq
Asked: 2022-01-11 11:19:49 +0800 CST2022-01-11 11:19:49 +0800 CST 2022-01-11 11:19:49 +0800 CST

PATH 中的通配符(环境变量)

  • 772

我在我的主目录中本地安装了一堆应用程序。为了让它们在全球范围内可用,我将它们添加PATH到.bashrc:

PATH="$PATH:/home/user/apps/app1/bin"
PATH="$PATH:/home/user/apps/app2/bin"
PATH="$PATH:/home/user/apps/appn/bin"

我怎样才能设置它,这样我就不必添加每个新的?我正在尝试这个,但它不起作用:

PATH="$PATH:/home/user/apps/*/bin"

注意:我知道我可以用循环添加它们,但我也担心我的PATH变量会变得太大,我想知道是否可以以某种方式对其进行通配符。

environment-variables bash
  • 3 3 个回答
  • 846 Views

3 个回答

  • Voted
  1. Best Answer
    Jeff Schaller
    2022-01-11T11:41:46+08:002022-01-11T11:41:46+08:00

    通配符不会被扩展$PATH,不会。根据bash 手册,PATH 是:

    以冒号分隔的目录列表, shell 在其中查找命令

    (我的重点)。

    来自另一个方向,手册的命令搜索和执行部分说,部分:

    如果名称既不是 shell 函数也不是内置函数,并且不包含斜杠,Bash 会在 $PATH 的每个元素中搜索包含该名称的可执行文件的目录。

    ...(我的重点)——它没有提到对路径元素进行的任何特殊处理,只是它们应该是目录(原样)。

    我不确定 bash 变量大小的限制是什么;我怀疑它是可用的内存。PATH 不需要导出,但很多人会这样做;如果它被导出,它需要与其他环境变量和参数一起适应getconf ARG_MAX(参考:https ://unix.stackexchange.com/a/124422/117549 )。一个大的 PATH 目录不应该引起太多的性能开销,因为 bash 使用哈希表来记住以前找到的命令的位置(每个会话)。

    如果您在将每个单独的应用程序目录添加到 PATH 时确实遇到了限制(视觉或技术),我建议您在 PATH 中添加一个“符号链接”目录,然后在其中链接来自各种应用程序的所需可执行文件。

    • 6
  2. Shaun Mitchell
    2022-08-21T21:58:54+08:002022-08-21T21:58:54+08:00

    我为此使用了一些解决方案:

    1.使用find动态生成$PATH

    为此,我使用了一些类似但略有修改的方法。假设您有以下结构:

    ~/apps
    ├── foo
    │   └── bin
    ├── bar
    │   └── bin
    └── blah
    

    我们可以...

    一个。将现有的apps/*/bin/文件夹添加到$PATH

    这将搜索/apps/*中的任何bin/目录,并将它们添加到shell 加载时,跳过任何没有bin/子目录的目录。$HOME$PATH

    #.bashrc
    
    bins=$(
        find "$HOME/apps/" -maxdepth 2 -type d -name 'bin' \
            | tr '\n' ':' \
            | sed 's/:$//'
    )
    export PATH="$bins:$PATH"
    

    产生:

    /home/user/apps/foo/bin:/home/user/apps/bar/bin:...
    

    湾。添加任何somedir/*/bin/到$PATH

    ...无论somedir/中的每个文件夹是否实际上都有一个bin/子目录。这意味着,对于上述目录结构,即使apps/blah/bin将被添加到$PATH-- 即使它不存在!

    当您的某个目录当前没有bin/子目录时,这很有用,但将来很有可能,并且您不想重新加载 shell 以便在您$PATH之后将其添加到您的创造它。

    #.bashrc
    
    bins=$(
        find "$HOME/apps/" -maxdepth 1 -type d \
            | sed 's_$_/bin_' \
            | tr '\n' ':' \
            | sed 's/:$//'
    )
    export PATH="$bins:$PATH"
    

    产生:

    /home/user/apps/foo/bin:/home/user/apps/bar/bin:/home/user/apps/blah/bin:...
    

    由于命令查找会短暂地尝试查找不存在的目录,并且将不存在的目录添加到我$PATH的 .

    2.stow用于生成可执行文件的符号链接

    stow正是为此目的而创建的。我目前正在使用此设置将我的所有 dotfiles 存储在 git repo 中并将它们复制到我的主目录:)

    如果您的目录结构如下:

    .
    ├── bar
    │   └── bin
    │       ├── bar-executable-1
    │       └── bar-executable-2
    ├── bin
    └── foo
        └── bin
            ├── foo-executable-1
            └── foo-executable-2
    

    并且您希望bar/bin/*和foo/bin/*中的所有文件都链接到bin/中,您可以运行:

    cd somedir
    stow -v --restow --target bin/ --dir bar/ bin
    stow -v --restow --target bin/ --dir foo/ bin
    

    注意:我--restow用于修剪,因为它会在重新创建新符号链接之前先删除所有旧符号链接

    这会产生:

    somedir
    ├── bar
    │   └── bin
    │       ├── bar-executable-1
    │       └── bar-executable-2
    ├── bin
    │   ├── bar-executable-1 -> ../bar/bin/bar-executable-1
    │   ├── bar-executable-2 -> ../bar/bin/bar-executable-2
    │   ├── foo-executable-1 -> ../foo/bin/foo-executable-1
    │   └── foo-executable-2 -> ../foo/bin/foo-executable-2
    └── foo
        └── bin
            ├── foo-executable-1
            └── foo-executable-2
    

    然后你可以简单地将somedir/bin/添加到你的PATH

    更stow容易使用

    如果

    1. 每个appN目录中的唯一目录是单个bin/目录,并且
    2. 您可以将编译后的bin/目录移到您的apps/目录之外

    那么你可以使用一个稍微简单的stow命令:

    /home/user
    ├── Desktop
    ├── Documents
    ├── Pictures
    ├── Videos
    ├── apps
    │   ├── bar
    │   │   └── bin
    │   │       ├── bar-executable-1
    │   │       └── bar-executable-2
    │   └── foo
    │       └── bin
    │           ├── foo-executable-1
    │           └── foo-executable-2
    └── bin
    
    cd
    stow -v --restow --target ./ --dir apps/ foo bar
    

    这基本上是在“apps”文件夹中查找名为“foo”和“bar”的“packages”,并使用 symlinks 将这两个包的全部内容复制到当前目录。因此,如果您在apps/foo/和apps/bar/中的所有内容都是一个bin/文件夹,那么这会在当前目录中生成一个bin/文件夹,其中包含指向apps/foo/bin/中所有文件的链接,并且应用程序/栏/bin/。

    但是,如果除了一个bin/目录之外,您在apps/foo/和apps/bar/中还有很多其他文件/文件夹,那么它也会在您的主文件夹中重新创建所有这些文件/文件夹,这可能是不可取的,你应该坚持第一个例子。stow

    https://www.gnu.org/software/stow/manual/html_node/Installing-Packages.html

    • 0
  3. Stéphane Chazelas
    2022-08-21T22:25:19+08:002022-08-21T22:25:19+08:00

    添加/home/user/apps/*/bin到$PATH意味着在路径为的目录中搜索可执行文件/home/user/apps/*/bin(完全有效的路径,没有什么可以阻止*字符¹在 Unix 上的文件或目录的名称中使用),您可以添加路径匹配的目录/home/user/apps/*/bin当时写作使用:

    path+=( /home/user/apps/*/bin(N-/) )
    

    在 zsh 中,$PATH变量与$pathcsh 中一样与数组绑定,并且-/glob 限定符可用于限制扩展为目录类型的文件(或符号链接到目录),以及Nnullglob

    您还可以发出 atypeset -U path来删除重复项(U表示唯一)。

    在fish中,其中$PATH作为数组公开,并且类似 nullglob 的行为适用于 中使用的 glob set:

    set PATH $PATH /home/user/apps/*/bin
    

    (但不限于目录类型的文件)。

    POSIXly,你总是可以这样做:

    for dir in /home/user/apps/*/bin; do
      [ -d "$dir" ] && PATH="${PATH:+$PATH:}$dir"
    done
    

    无论如何,如果稍后将更多目录添加到 /home/user/apps/ 中,它们将不会自动出现在$PATH.

    在 ksh93 中,您可以使用规则来实现这种魔法:

    function PATH.get {
      typeset dir
      for dir in ~(N)/home/user/apps/*/bin; do
        [[ :$PATH: = *:"$dir":* || ! -d $dir ]] || PATH=${PATH:+$PATH:}$dir
      done
    }
    

    $PATH每次引用时都会计算的值。

    在 zsh 中,您可以在每个提示之前使用precmd()钩子或bashusing重新计算它$PROMPT_COMMAND。


    ¹ 或除 NUL 以外的任何字符/,甚至是非字符。

    • 0

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve