bash 如何最好地包含其他脚本?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/192292/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How best to include other scripts?
提问by Aaron H.
The way you would normally include a script is with "source"
通常包含脚本的方式是使用“源”
eg:
例如:
main.sh:
主文件:
#!/bin/bash
source incl.sh
echo "The main script"
incl.sh:
包括.sh:
echo "The included script"
The output of executing "./main.sh" is:
执行“./main.sh”的输出是:
The included script
The main script
... Now, if you attempt to execute that shell script from another location, it can't find the include unless it's in your path.
... 现在,如果您尝试从另一个位置执行该 shell 脚本,除非它在您的路径中,否则它无法找到包含。
What's a good way to ensure that your script can find the include script, especially if for instance, the script needs to be portable?
确保您的脚本可以找到包含脚本的好方法是什么,尤其是在脚本需要可移植的情况下?
采纳答案by Chris Boran
I tend to make my scripts all be relative to one another. That way I can use dirname:
我倾向于让我的脚本都相互关联。这样我就可以使用目录名:
#!/bin/sh
my_dir="$(dirname "DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
. "$DIR/incl.sh"
. "$DIR/main.sh"
")"
"$my_dir/other_script.sh"
回答by sacii
I know I am late to the party, but this should work no matter how you start the script and uses builtins exclusively:
我知道我迟到了,但是无论您如何启动脚本并专门使用内置函数,这都应该有效:
scriptPath=$(dirname scriptPath=${0%/*}
)
.
(dot) command is an alias to source
, $PWD
is the Path for the Working Directory, BASH_SOURCE
is an array variable whose members are the source filenames, ${string%substring}
strips shortest match of $substring from back of $string
.
(dot) command 是 的别名source
,$PWD
是工作目录的路径,BASH_SOURCE
是一个数组变量,其成员是源文件名,${string%substring}
从 $string 后面去除 $substring 的最短匹配
回答by tardate
An alternative to:
替代方案:
#!/bin/bash
source $(dirname #!/bin/sh
MY_DIR=$(dirname $(readlink -f readlink - display value of a symbolic link
...
-f, --canonicalize
canonicalize by following every symlink in every component of the given
name recursively; all but the last component must exist
))
$MY_DIR/other_script.sh
)/incl.sh
echo "The main script"
is:
是:
readlink - display value of a symbolic link
...
-f, --canonicalize
canonicalize by following every symlink in every component of the given
name recursively; all but the last component must exist
.. the advantage being not having the dependence on dirname, which is not a built-in command (and not always available in emulators)
.. 优点是不依赖于 dirname,这不是内置命令(并不总是在模拟器中可用)
回答by dsm
If it is in the same directory you can use dirname $0
:
如果它在同一目录中,您可以使用dirname $0
:
#!/bin/bash # Full path of the current script THIS=`readlink -f "${BASH_SOURCE[0]}" 2>/dev/null||echo` # The directory where current script resides DIR=`dirname "${THIS}"` # 'Dot' means 'source', i.e. 'include': . "$DIR/compile.sh"SRC=$(cd $(dirname "
"); pwd) source "${SRC}/incl.sh"source "$( dirname "${BASH_SOURCE[0]}" )/incl.sh"
回答by Mat131
I think the best way to do this is to use the Chris Boran's way, BUT you should compute MY_DIR this way:
我认为最好的方法是使用 Chris Boran 的方法,但你应该这样计算 MY_DIR:
# Copyright https://stackoverflow.com/a/13222994/257479
script_root=$(ls -l /proc/$$/fd | grep "255 ->" | sed -e 's/^.\+-> //')
To quote the man pages for readlink:
引用 readlink 的手册页:
# Copyright http://stackoverflow.com/a/7400673/257479 myreadlink() { [ ! -h "" ] && echo "" || (local link="$(expr "$(command ls -ld -- "")" : '.*-> \(.*\)$')"; cd $(dirname ); myreadlink "$link" | sed "s|^\([^/].*\)$|$(dirname )/|"); } whereis() { echo | sed "s|^\([^/].*/.*\)|$(pwd)/|;s|^\([^/]*\)$|$(which -- )|;s|^$||"; } whereis_realpath() { local SCRIPT_PATH=$(whereis ); myreadlink ${SCRIPT_PATH} | sed "s|^\([^/].*\)$|$(dirname ${SCRIPT_PATH})/|"; } script_root=$(dirname $(whereis_realpath "
"))#!/bin/bash installpath=/where/your/scripts/are . $installpath/incl.sh echo "The main script"
##代码##
I've never encountered a use case where MY_DIR
is not correctly computed. If you access your script through a symlink in your $PATH
it works.
我从未遇到过MY_DIR
计算不正确的用例。如果您通过符号链接访问您的脚本,$PATH
则它可以工作。
回答by Brian Haak
A combination of the answers to this question provides the most robust solution.
这个问题的答案组合提供了最可靠的解决方案。
It worked for us in production-grade scripts with great support of dependencies and directory structure:
它在生产级脚本中为我们工作,并为依赖项和目录结构提供了极大的支持:
##代码##The method supports all of these:
该方法支持所有这些:
- Spacesin path
- Links(via
readlink
) ${BASH_SOURCE[0]}
is more robust than$0
- 路径中的空格
- 链接(通过
readlink
) ${BASH_SOURCE[0]}
比$0
回答by Max
回答by Alessandro Pezzato
This works even if the script is sourced:
即使脚本来源也是如此:
##代码##回答by Alexar
1. Neatest
1. 最整洁
I explored almost every suggestion and here is the neatest one that worked for me:
我研究了几乎所有的建议,这里是最适合我的建议:
script_root=$(dirname $(readlink -f $0))
script_root=$(dirname $(readlink -f $0))
It works even when the script is symlinked to a $PATH
directory.
即使脚本符号链接到$PATH
目录,它也能工作。
See it in action here: https://github.com/pendashteh/hcagent/blob/master/bin/hcagent
在这里查看它的实际效果:https: //github.com/pendashteh/hcagent/blob/master/bin/hcagent
2. The coolest
2.最酷
##代码##This is actually from another answer on this very page, but I'm adding it to my answer too!
这实际上来自此页面上的另一个答案,但我也将其添加到我的答案中!
2. The most reliable
2.最可靠
Alternatively, in the rare case that those didn't work, here is the bullet proof approach:
或者,在极少数情况下那些不起作用,这里是防弹方法:
##代码##You can see it in action in taskrunner
source: https://github.com/pendashteh/taskrunner/blob/master/bin/taskrunner
您可以在taskrunner
源代码中看到它的实际效果:https: //github.com/pendashteh/taskrunner/blob/master/bin/taskrunner
Hope this help someone out there :)
希望这可以帮助那里的人:)
Also, please leave it as a comment if one did not work for you and mention your operating system and emulator. Thanks!
另外,如果有人不适合您,请留下评论并提及您的操作系统和模拟器。谢谢!
回答by Steve Baker
You need to specify the location of the other scripts, there is no other way around it. I'd recommend a configurable variable at the top of your script:
您需要指定其他脚本的位置,别无他法。我建议在脚本顶部使用一个可配置变量:
##代码##Alternatively, you can insist that the user maintain an environment variable indicating where your program home is at, like PROG_HOME or somesuch. This can be supplied for the user automatically by creating a script with that information in /etc/profile.d/, which will be sourced every time a user logs in.
或者,您可以坚持让用户维护一个环境变量,指示您的程序所在的位置,例如 PROG_HOME 或类似的。这可以通过在 /etc/profile.d/ 中创建包含该信息的脚本自动为用户提供,每次用户登录时都会提供该信息。