是什么区别sh
和source
?
source: source filename [arguments]
Read and execute commands from FILENAME and return. The pathnames
in $PATH are used to find the directory containing FILENAME. If any
ARGUMENTS are supplied, they become the positional parameters when
FILENAME is executed.
而对于man sh
:
NAME
bash - GNU Bourne-Again SHell
SYNOPSIS
bash [options] [file]
COPYRIGHT
Bash is Copyright (C) 1989-2004 by the Free Software Foundation, Inc.
DESCRIPTION
Bash is an sh-compatible command language interpreter that executes commands read from the standard input or from a file. Bash also incorporates
useful features from the Korn and C shells (ksh and csh).
Bash is intended to be a conformant implementation of the IEEE POSIX Shell and Tools specification (IEEE Working Group 1003.2).
当你调用source
(或它的别名.
), 插入在当前 bash进程的脚本。 所以你可以读通过脚本设置变量。
当你调用sh
,你开始运行的一个新的会话叉 (子进程) /bin/sh
,这通常是一个符号链接bash
。 在这种情况下,当子脚本完成由子脚本设置环境变量将被丢弃。
注意 : sh
可能是一个符号链接到另一个 shell。
一个小样本
例如,如果你想通过特定的方式来改变当前的工作目录 ,你不能这样做
cat <<eof >myCd2Doc.sh
#!/bin/sh
cd /usr/share/doc
eof
chmod +x myCd2Doc.sh
这不会做你所期望的:
cd /tmp
pwd
/tmp
~/myCd2Doc.sh
pwd
/tmp
因为当前的工作目录是环境的一部分, myCd2Doc.sh
将在一个子shell中运行。
但:
cat >myCd2Doc.source <<eof
# Shell source file
myCd2Doc() {
cd /usr/share/doc
}
eof
. myCd2Doc.source
cd /tmp
pwd
/tmp
myCd2Doc
pwd
/usr/share/doc
(我写的一个小样本mycd
功能。)
执行层$SHLVL
cd /tmp
printf %b '\43\41/bin/bash\necho This is level \44SHLVL.\n' >qlvl.sh
bash qlvl.sh
This is level 2.
source qlvl.sh
This is level 1.
小递归
cat <<eoqlvl >qlvl.sh
#!/bin/bash
export startLevel
echo This is level $SHLVL starded:${startLevel:=$SHLVL}.
((SHLVL<5)) && ./qlvl.sh
eoqlvl
chmod +x qlvl.sh
./qlvl.sh
This is level 2 starded:2.
This is level 3 starded:2.
This is level 4 starded:2.
This is level 5 starded:2.
source qlvl.sh
This is level 1 starded:1.
This is level 2 starded:1.
This is level 3 starded:1.
This is level 4 starded:1.
This is level 5 starded:1.
而最后的测试:
printf %b '\43\41/bin/bash\necho Ending this.\nexit 0\n' >finalTest.sh
bash finalTest.sh
Ending this.
source finalTest.sh
Ending this.
...您可能会注意到两者之间的语法不同的行为。 ;-)
主要的区别是,它们在不同的处理中执行。
所以,如果你source
文件foo
它做了cd
,采购外壳(例如,在终端的交互shell)受到影响(以及它的当前目录下会发生变化)
如果执行sh foo
的cd
不影响采购外壳,只有新创建的sh
进程中运行foo
阅读高级Bash脚本编程指南 。
这种差别不是具体到Linux; 每POSIX实现将有它。
正如其他人所说,当你运行sh test.sh
,任何改变test.sh
让你的shell环境不会在过程结束之后仍然存在。
但是,也请注意,未出口环境的任何元素(如变量,别名和shell函数)将不会提供给在代码test.sh
当它作为一个子(即执行sh test.sh
)。
例如:
$ cat > test.sh
echo $foo
$ foo=bar
$ sh test.sh
$ . test.sh
bar
实施例2:
lap@my-ThinkPad:~$ cat test.sh
#!/bin/sh
cd /etc
lap@my-ThinkPad:~$ sh test.sh
lap@my-ThinkPad:~$ pwd
/home/savoury
lap@my-ThinkPad:~$ source test.sh
lap@my-ThinkPad:/etc$ pwd
/etc
lap@my-ThinkPad:/etc$