采购(“。”或“源”)与在bash中执行文件之间有什么区别?


76

执行这样的脚本有什么区别:

./test.sh

并执行如下脚本:

. test.sh

我尝试了一个简单的两行脚本,以查看是否可以找到区别:

#!/bin/bash
ls

但是两者. test.sh./test.sh返回相同的信息。


抱歉,如果这是重复的内容-经过进一步调查,我通过搜索'bash dot'而不是'bash'找到了一些具有相关信息的页面。
纳丹

3
就像和(第一个调用搜索)test.sh不一样一样,并且以相同的方式(第一个调用搜索)也不同。在执行路径搜索时,许多外壳似乎隐式包含在外壳的末尾,但是这种行为不是标准的。因此,比较vs 和vs 比较准确。./test.shPATH. test.sh. ./test.shPATH.PATH.test.sh. test.sh./test.sh. ./test.sh
jw013

Answers:


83

./test.shtest.sh作为一个单独的程序运行。如果文件test.sh以开头,则可能是bash脚本#!/bin/bash。但这可能完全是另外一回事。

. ./test.shtest.sh在正在运行的bash实例中执行文件的代码。它的工作方式就像内容文件test.sh是文本形式而非. ./test.sh行形式。(几乎:有一些细节有所不同,例如的值$BASH_LINENOreturn内置函数的行为。)

source ./test.sh. ./test.shbash中的相同(在其他shell中,source可能略有不同或完全不存在;.因为包含在POSIX标准中)。

./test.sh带有.内置脚本的脚本和包含内置脚本的脚本之间运行最明显的区别是,如果test.sh脚本使用单独的进程设置了一些环境变量,则仅设置子进程的环境,而包含脚本的环境被设置。设置唯一的外壳过程。如果您添加一行foo=bartest.sh,并echo $foo在调用脚本的末尾,你会看到其中的差别:

$ cat test.sh
#!/bin/sh
foo=bar
$ ./test.sh
$ echo $foo

$ . ./test.sh
$ echo $foo
bar

17
此外echo $$,将脚本添加到脚本中也会显示出明显的区别。该$$变量保存当前shell的PID。

1
另一个使用场景是使用. ./test.sh来自另一个Shell脚本中的调用来使用test.sh中描述的功能。我的意思是,不仅可以设置变量,还可以以这种方式创建新函数,然后可以从bash或其他脚本中调用它们。. /usr/libexec/company/tools; custom_command "variable
Rqomey

9

第一种方式运行脚本会将其作为子进程运行。另一方面,Sourcing(第二种方式)将运行脚本,就像您将其所有命令输入到当前外壳中一样-如果脚本设置了变量,它将保持设置状态;如果脚本退出,则会话将退出。请参阅help .以获取文档。


3

我要注意的另一件事是,如果您有这样的别名:

# add into .bashrc_aliases
alias ls='ls -lht'

这样,./test.sh您将获得正常的ls输出(以及与当前Shell不同的PID):

auraham@pandora:~/iso$ ./test.sh 
dsl-4.4.10.iso  test.sh
3136 # PID

使用. test.sh或,. ./test.sh您将获得更详细的输出(与当前shell相比具有相同的PID):

auraham@pandora:~/iso$ echo $$
2767 # shell PID

auraham@pandora:~/iso$ . test.sh 
total 50M
drwxrwxr-x  2 auraham auraham 4.0K Jul 30 15:41 .
-rwxrwxr-x  1 auraham auraham   32 Jul 30 15:41 test.sh
drwxr-xr-x 50 auraham auraham 4.0K Jul 30 15:30 ..
-rw-rw-r--  1 auraham auraham  50M Jul 28 17:24 dsl-4.4.10.iso
2767 # PID

您可以在中添加它,.bashrc if [ -f ~/.bash_aliases ]; then . ~/.bash_aliases fi 然后在中添加别名.bash_aliases
auraham

当然可以,但是您是否还不必使用alias关键字?(也许这只是您在第3行上发布的错误?)
伊曼纽尔·伯格

完全正确,我的错误。感谢@EmanuelBerg
auraham

-1

对我而言source(或.)的主要用法是bash函数

我的脚本具有很多功能,我可以通过自己的脚本执行所有这些脚本.bashrc。函数“成为”命令,这是我经常使用的命令。


我在.bashrc中尝试了所有三种方法-源代码,脚本的绝对位置和命令的名称(将脚本放在PATH文件夹中)-三种方法均有效。
伊曼纽尔·伯格
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.