这是一个简单的示例,显示declare在脚本中使用脚本将不会运行,而获取脚本将:
$ cat /tmp/new
#! /bin/sh
declare -i hello
$ chmod a+rwx /tmp/new
$ /tmp/new
/tmp/new: 3: declare: not found
$ source /tmp/new
$
Run Code Online (Sandbox Code Playgroud)
我想知道为什么直接运行脚本不起作用,而采购它呢?我怎样才能使第一个工作?谢谢!
我知道可以通过引用命令本身来绕过别名。
但是,似乎如果内置命令被同名函数“遮蔽”,则无法执行底层内置命令,除非...使用内置命令。如果你能做到。
引用 bash 手册页 (at LESS='+/^COMMAND EXECUTION' man bash):
COMMAND EXECUTION
After a command has been split into words, if it results in a simple
command and an optional list of arguments, the following actions are
taken.
If the command name contains no slashes, the shell attempts to locate
it. If there exists a shell function by that name, that function is
invoked as described above in FUNCTIONS. If the name does not match a
function, the shell …Run Code Online (Sandbox Code Playgroud) 打字man alias给我
无需手动输入别名
同样的事情也适用于export和eval。起初我认为它只发生在 shell 内置命令中,但man echo给了我手册页。
除了谷歌搜索,有没有办法查看这些命令的文档?如果没有,有没有办法“安装”那些丢失的手册页?
我有两种调用printf系统的方法:
$ type -a printf
printf is a shell builtin
printf is /usr/bin/printf
$ file /usr/bin/printf
/usr/bin/printf: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically
linked (uses shared libs), for GNU/Linux 2.6.32,
BuildID[sha1]=d663d220e5c2a2fc57462668d84d2f72d0563c33, stripped
Run Code Online (Sandbox Code Playgroud)
因此,一个是内置的 bash,另一个是正确编译的可执行文件。我本来期望一个程序的唯一工作是printf比内置的 shell 快得多。当然,内置函数已经加载到内存中,但在专用程序中实际执行时间应该更快,对吗?它会被优化以在最好的 Unix 哲学中很好地做一件事。
显然不是:
$ >/tmp/foo; time for i in `seq 1 3000`; do printf '%s ' "$i" >> /tmp/foo; done;
real 0m0.065s
user 0m0.036s
sys 0m0.024s
$ >/tmp/foo; time for i in `seq 1 3000`; do /usr/bin/printf …Run Code Online (Sandbox Code Playgroud) 考虑以下命令:
exit > /dev/null
exit | cat
Run Code Online (Sandbox Code Playgroud)
在一些 shell(ksh、bash、(d)ash)上,行为是相同的:第一个命令导致 shell 立即退出,而第二个命令没有可见的行为。
我得出的结论是,第一个命令不涉及 fork(2),而第二个命令涉及两个(一个用于执行exit,另一个用于 execve(2) cat)。
我查看了 POSIX 规范第 2.14 节,但没有找到任何明确说明这一点的内容。
POSIX 是否指定某些命令不得 fork(2) 而另一些命令必须?标准是否可以接受为第一个命令生成子 shell?
我知道( exit )永远不应该退出当前 shell,因为括号会生成一个实际执行命令的子 shell exit,这意味着子 shell 将立即退出。但是,我不确定重定向和管道,因为这里没有括号。
我问这个问题是因为在最近的课程实验室中,我们被告知要实现一个最小的 Unix shell。我们可以实现许多“可选功能”,以供补充。这些“可选功能”之一是组合重定向和管道。我们有一些不同的实现,我相信其中一些比其他实现更接近 POSIX 的指定行为,因此我想知道实际行为是如何指定的。
我知道该命令command是在最新的 POSIX 标准中指定的,而builtin不是。我也意识到这两个命令都是常规的内置命令(即它们可以被用户定义的函数覆盖)。一些外壳定义了builtin,但不是全部(例如dash没有)。我想了解为什么builtin在某些 shell 中引入。
据我所知,builtin只会返回特殊的然后是常规的内置函数,但是command会返回特殊的内置函数,然后是常规的内置-p函数,然后是路径上的命令(并且可以使用开关command来指定它使用外壳定义的默认值$PATH,以防用户修改$PATH)。
例如,在 中mksh,我看到以下内容:
(注意: mksh从 repo 安装在 Ubuntu 20.04 上http://archive.ubuntu.com/ubuntu focal/universe amd64 mksh amd64 58-1)
$ echo $KSH_VERSION
@(#)MIRBSD KSH R58 2020/03/27
$ which -a echo
/usr/bin/echo
/bin/echo
$ which -a printf
/usr/bin/printf
/bin/printf
$ type echo
echo is a shell builtin
$ …Run Code Online (Sandbox Code Playgroud) 我知道外部命令是通过创建一个单独的进程在 shell 中运行的,但是在 shell 中运行内置命令时究竟会发生什么?
它们是作为函数执行的,还是 shell 创建一个新线程来执行它们?
我能够运行一个名为“HOME”的命令,它似乎等同于cd && echo "~". 但我无法弄清楚它是在哪里定义的:
$ pwd
/tmp
$ which HOME
HOME not found
$ type HOME
HOME not found
$ man HOME
No manual entry for HOME
$ HOME
~
$ pwd
/Users/tba
Run Code Online (Sandbox Code Playgroud)
这是内置的shell吗?这似乎更像是打印我的主目录的完全限定路径的失败尝试。
我在 OS X Yosemite 上运行 ZSH(使用 Oh-My-Zsh)。
所以我正在阅读The Linux Command Line一书,它说命令有四种类型:
(1) 可执行程序
(2) shell 内置函数
(3)shell函数(shell脚本)
(4) 别名
然后它说为了识别命令的类型,您可以使用该type命令。
但是,我注意到该type命令无法区分 shell 函数(shell 脚本)和可执行命令。
例如:
type cp
(will output: cp is /bin/cp)
type bzexe
(will output: bzexe is /bin/bzexe)
Run Code Online (Sandbox Code Playgroud)
但是,我们都知道它cp是一个可执行程序,bzexe是一个shell脚本。
所以我现在的问题是:我们可以使用什么命令来区分这两者?
我知道这个file命令,它工作正常。这是唯一的解决方案吗?
#!/bin/sh
foo() {
echo "in foo"
}
type foo
Run Code Online (Sandbox Code Playgroud)
checkbashisms.pl明明不喜欢type,为什么?
$ checkbashisms.pl foo.sh
possible bashism in foo.sh line 7(type):
type foo
Run Code Online (Sandbox Code Playgroud)
不是POSIX吗?但是所有常见的外壳都支持它(即bash, zsh, dash, busybox sh, mksh; 甚至在ksh; 也许只是csh不支持它),难道不应该有一种方法来抑制这个警告吗?
shell-builtin ×10
shell ×5
bash ×2
command ×1
command-line ×1
executable ×1
function ×1
history ×1
man ×1
performance ×1
pipe ×1
posix ×1
shell-script ×1
thread ×1
zsh ×1