我对“只有一个点 - 空格 - shell 脚本名称”(如. myshellscript
)和“shell 脚本路径”(如./myshellscript
)命令感到困惑。
他们是为了什么?我注意到该命令. myshellscript
即使使用 -rw-rw-r-- 也会执行 shell 脚本。但./myshellscript
事实并非如此。所以我很困惑。
答案1
help source
说:
source: source filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.
source
是 的同义词.
,这意味着您可以同时写
. myshellscript
或者
source myshellscript
它们的作用:source
读取文件的每一行(逐行)并在当前 shell 中执行它。
但./myshellscript
执行当前目录中的文件(如果有权限)。这也可以是
/tmp/foo/bar/myshellscript
(执行myshellscript
目录中的文件/tmp/foo/bar
)或
/usr/local/bin/myshellscript
这意味着,这里的点只是当前目录。因此执行当前目录中./myshellscript
调用的文件。myshellscript
例如尝试
cd .
更改为当前目录(没有真正的更改;-))或
ls .
其中列出了当前目录的内容。
正如@Alvin Wong 评论的那样:你可以尝试这个脚本
#!/bin/foobarNonExisting
echo "This is the Shell that executes me:"
echo $SHELL
with.
或source
to see,它不读取 shebang。它只使用您当前的 shell。执行脚本本身会导致错误。
答案2
其他人表示区别在于采购与执行,但没有人概述其中的区别功能性的差异。
最大的功能差异是exit
,cd
如果您获取当前运行的 shell,则 、 和 变量赋值将影响当前运行的 shell,但如果执行它,则不会影响。要进行演示,请尝试以下操作:
$ cat test.sh
#!/bin/bash
mkdir -p test
cd test
pwd
foo=bar
echo script foo: $foo
$ ./test.sh
/Users/kevin/test
script foo: bar
$ echo $foo
$ pwd
/Users/kevin
$ . test.sh
/Users/kevin/test
script foo: bar
$ echo $foo
bar
$ pwd
/Users/kevin/test
$
现在试试这个:
$ cat test.sh
#!/bin/bash
exit
$ ./test.sh
$ . test.sh
[Process completed]
正如您所看到的,exit
在执行的脚本中将完成该脚本,但如果您使用 来获取脚本exit
,它将退出当前的 shell!
答案3
在 bash 中,.
在source
功能上执行相同的工作——在当前 shell 内运行脚本。
./foo
在另一个 shell 中运行,因为您的 shell 在执行之前分叉。
如果您的脚本应该是可移植的,请始终使用.
.source
是 bash 的同义词,但在 POSIX 中不存在。
答案4
有很多答案解释说. ~/bin/script.sh
相当于source ~/bin/script.sh
.这是的解释为什么。
我有几个用于测试的集群,我使用环境变量来指向它们。通常,当您运行脚本时,其中设置的任何变量都保留在该脚本的范围内。在示例中:
$ echo $MYFIELD #Nothing set
$ cat test.sh
export MYFIELD=foo #This would set it
$ ./test.sh
$ echo $MYFIELD #Didn't work because the script didn't carry it back to its parent
$ . ./test.sh
$ echo $MYFIELD #When run as a sourced script, this stayed in the context of my current shell
foo
通过这种方式,我可以. ~/env/cluster7
在该集群上键入并运行我想要的任何命令,然后键入. ~/env/cluster3
以更改所有环境变量以指向另一个环境变量,而无需手动设置它们。
请注意“。”行首后跟空格被解释为命令。这是可以的,因为您永远不会执行唯一可以这样命名的文件:当前目录。但是,在任何其他上下文中,例如没有后续空格或在命令行后面的任何点,它指的是路径,因此. ./test.sh
.由于它被 bash 视为命令,. test.sh
因此也有效。