在Bash中,获取文件(仅当文件存在时)的最简洁方法是什么?

38

Bash脚本中,是否有一种单语句的替代方法?

if [ -f /path/to/some/file ]; then
    source /path/to/some/file
fi

最重要的是文件名只出现一次,不要将其作为变量(这会增加更多的代码行)。

例如,在PHP中,您可以这样做

@include("/path/to/some/file"); // @ makes it ignore errors

1
重要阅读:https://unix.stackexchange.com/questions/450239/why-check-for-file-existence-before-sourcing-it - Jesse Nickles
8个回答

46

自定义 @include 版本是一种选择吗?

include () {
    [[ -f "$1" ]] && source "$1"
}

include FILE

如果源脚本引用其位置参数,则此方法无法按预期工作。请参见此问题。我想知道为什么在过去的8年中没有人指出这一点。 - ynn
你的意思是 include FILE a b csource FILE a b c 是等价的吗? - chepner
我不明白你为什么认为第一个参数会被加倍,除非你写的是 source "$1" "$@"。至于为什么我没有使用 "$@",那只是因为在原始问题中它并不是必需的。 - chepner
这是我想说的话:https://repl.it/repls/LightblueTriangularLoopfusion(在线编辑器) - ynn
没问题。不过这与本问题并没有太大关系,因为本问题从未提到需要向要被源化的文件传递参数。 - chepner
不行。即使对于这个问题也很重要。问题在于是否传递了一个额外的参数。这可能是灾难性的:https://repl.it/repls/ProfitableInsecureCallback - ynn

18

如果你关心一个不重复文件名的一行代码,可以考虑这样:

FILE=/path/to/some/file && test -f $FILE && source $FILE

如果 set -ex 超出您的控制(例如在构建环境中),那么这就是您想要的答案。 - vcardillo

13

如果您关心警告(且源文件不存在对于您的脚本并不是关键),只需消除该警告:

source FILE 2> /dev/null

文件是可选的,因此可以预期缺少它,但这是否也会丢弃所包含脚本生成的任何输出? - Bart van Heukelom
@BartvanHeukelom:是的,但它只会丢弃脚本发送到标准错误的任何输出。脚本发送到标准输出的任何输出都将正常传输。 - ayaz

5
您可以尝试:
test -f $FILE && source $FILE

如果test返回false,则不会评估&&的第二部分。

1
稍微好一些,但我更喜欢只有一个$FILE(已更新问题)。 - Bart van Heukelom
既然它是一个变量,那么它的值将是一致的,我认为你不应该担心它。 - Attila
这就是了,它不一定是一个变量。 - Bart van Heukelom
你可以将名称分配给一个变量,然后将问题简化为一个我的答案是解决方案的问题(这样你就不会重复文件名)。 - Attila

4
这是我能得到的最短的文件名加20个字符:
F=/path/to/some/file;[ -f $F ] && . $F

这相当于:

F=/path/to/some/file 
test -f $F && source $F

为了提高可读性,我更喜欢这种形式:
FILE=/path/to/some/file ; [ -f $FILE ] && . $FILE

4

如果您希望始终获得干净的退出代码,并且不管发生什么情况都能够继续运行,则可以执行以下操作:

source ~/.bashrc || true && echo 'is always executed!'

如果你还想消除错误信息,那么:

source ~/.bashrc 2> /dev/null || true && echo 'is always executed!'

1

如果您不关心脚本的输出,您可以使用以下命令将标准错误重定向到/dev/null

$ source FILE 2> /dev/null


-1

我可以发帖,但由于声望不够,不能评论,因此这是对那里面答案的扩展。如果我能评论,我就不会发布看起来像重复回答的内容。在开始挑剔和抱怨它是重复内容之前,请重新阅读我刚才说的话。

include () { test -f "$1" && . "$@"; }


1
没有“最高答案”。其他答案并不总是在你的上面。当你输入答案时,它们可能会在你的上方 - 但是一旦发布后,它们会按照页面排序,包括你的答案。排序的标准有“趋势”,“最高分数”,“修改日期”和“创建日期”。根据这些参数,您的答案将被放置在页面上。此外,请避免使用贬低性评论。 - Eric Aya
这并没有回答问题。一旦您拥有足够的声望,您将能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - helvete

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接