问题描述
我在我的bash脚本如下code。现在,我想在POSIX sh的使用它。因此,如何将它转换?谢谢。
DIR =$(光盘$(目录名称$ {BASH_SOURCE [0]})>的/ dev / null的&放大器;&安培; PWD)
在POSIX的shell( 买者:关键的区别是,如果你的脚本被的来源的(装入的电流的外壳采用 在简单的情况下,这会做(业务方案的命令在相当于) $ BASH_SOURCE $的
SH
)对应C $ C>是 $ 1,0
。 。
)在下面的片段会的不的正常工作。
DIR = $(CDPATH = CD - $(目录名称 - $ 0)&放大器;&安培; PWD)
如果你也想为解决的产生的目录路径,其最终目标的情况下,目录和/或其组成部分的符号链接的添加 -P
到 PWD
命令:
DIR = $(CDPATH = CD - $(目录名称 - $ 0)&放大器;&安培; PWD -P)
买者:这是不会一样找到脚本本身的起源的真实目录:结果
比方说,你的脚本富
被链接到的/ usr / local / bin目录/富
在 $ PATH
,但其真正的路径是 / foodir /斌/富
。结果
以上仍然报告的/ usr / local / bin目录
,因为符号链接分辨率( -P
)被应用到目录的的/ usr / local / bin目录
,而不是脚本本身。
要找到脚本自身起源的真正目录,你必须检查的脚本的路径,看看它是否是一个符号链接,如果是这样,按照(符号链接的最终目标文件)链,然后从的目标的文件的规范路径解压的目录路径。
GNU的的readlink -f
(更好:的readlink -e
),可以为你做的,但的readlink
不是POSIX实用程序。结果
在事实上,有的没有的POSIX解决程序的文件的符号链接即可。
有办法解决的,但他们麻烦,不完全健壮的:
在下, POSIX兼容的shell函数的实施什么GNU的的readlink -e
确实,是一个合理可靠的解决方案的只有失败两种罕见的边缘情况
- 与路径内嵌的换行的(很少见)
- 包含文字字符串
文件名 - >
(也少见)
通过这个功能,命名为 rreadlink
定义,以下决定起源的脚本的真实目录路径
DIR = $(目录名称 - $(rreadlink$ 0))
rreadlink()
源$ C $ C - 地方的前的调用它在脚本:
rreadlink()(#执行功能的一个子shell * *本地化变量和cd`的`效果。 TARGET = $ 1 = FNAME = TARGETDIR = CDPATH #尽量让执行环境为predictable尽可能:
#所有命令下面通过`command`调用的,所以我们必须确保`command`
#本身不会重新定义为别名或shell函数。
#(请注意,命令跨越炮弹太不协调,所以我们不使用它。)
#`command`是bash中,破折号和ksh,zsh的一个*内置*,有些平台甚至没有
#它的外部工具的版本(例如,Ubuntu的)。
#`command`绕过别名和shell函数,也发现建宏
#在bash,破折号和ksh。在zsh中,选择POSIX_BUILTINS必须打开该
# 即将发生。
{\\ unalias命令; \\取消设置-f命令; }>的/ dev / null的2 - ;&放大器; 1
[-n$ ZSH_VERSION]&放大器;&安培;选项[POSIX_BUILTINS] =#上的zsh做*找到内建*用`command`了。 而:;做#,直至最终目标是找到解决潜在的符号链接。
[-L$目标] || [-e$目标] || {printf的命令,'%s的\\ n'ERROR:'$目标'不存在。 >和2;返回1; }
命令cd$(命令目录名称 - $目标)#切换到目标目录;必要的目标路径的正确的分辨率。
FNAME = $(命令基名 - $目标)#提取文件名。
[$ FNAME='/']放大器;&安培; FNAME =''#!奇怪的是,`基本名/`返回'/'
如果[-L$ FNAME];然后
#提取[下一页]目标路径,可以被定义
#*相对*的符号链接自己的目录。
#注:我们解析`LS -l`输出找到链接目标
#这是唯一符合POSIX标准,尽管有些脆弱,方式。
目标= $(ls -l命令$ FNAME)
目标= $ {#目标* - > }
继续解析#【下一步】链接目标。
科幻
打破#最终目标达到了。
DONE
TARGETDIR = $(pwd命令-P)#得到规范的目录。路径
#输出最终目标的标准路径。
#请注意,我们手动解决/结束路径。和/ ..以确保我们有一个标准化的路径。
如果[$ FNAME=。 ];然后
命令的printf'%s的\\ n'$ {TARGETDIR%/}
ELIF [$ FNAME=..];然后
#警告:像在/ var / ..将解析/私营(假设的/ var @ - > /私营/ VAR),即'..'应用
#规范化了。
命令的printf'%s的\\ n'$(命令目录名称 - $ {} TARGETDIR)
其他
命令的printf'%s的\\ n'$ {TARGETDIR%/} / $ FNAME
科幻
)
要成为稳健和predictable,函数使用命令
,以确保只有shell内建命令或外部工具分别被称为(忽略重载别名和函数的形式)。结果
它已经在最新版本以下的炮弹进行测试:庆典
,破折号
, KSH
,的zsh
。
对于如何处理的来源的调用
TL;博士
使用POSIX功能只:
- 您的不能够的决定脚本路径在的来源的调用(除
zsh的
,其中,但是,通常并不作为SH
)。 - 您的可以的检测是否的脚本正在来源只有当你的脚本正在采购的直接的由壳(如外壳轮廓/初始化文件;可能通过的链的sourcings的),通过比较
$ 1,0
到外壳可执行文件的名称/路径(除了在的zsh
,其中,如上所述$ 1,0
确实是当前脚本的路径)。相比之下(除的zsh
),脚本正在从采购的另一个脚本的是本身的直接引用的,包含是的脚本的路径$ 1,0
。 - 为了解决这些问题,
庆典
,KSH
和的zsh
有无的非标准的特点是做的允许确定实际脚本路径甚至在了源代码的情况,也检测脚本是否正在采购或不;例如,在庆典
,$ BASH_SOURCE
的总是的包含了运行脚本的路径,无论是正在采购或没有,[$ 0!=$ BASH_SOURCE]]
可用于测试脚本是否正在采购。
要说明为什么不能做,让我们从分析命令
#不建议 - 见下文的讨论。
DIR = $(CD-P - $(目录名称 - $(命令-v - $ 0))和安培;&安培; PWD -P)
- (二旁白:
- 使用
-P
两次是多余的 - 这是足以与PWD
使用 - 命令缺少
CD
的潜在标准输出输出的沉默,如果$ CDPATH
情况进行设置。 )
- 使用
-
命令-v - $ 0
-
命令-v - $ 0
旨在涵盖一个额外的场景:如果脚本正在的来源的从的互动的外壳,$ 1,0
通常包含的只是文件名的外壳可执行文件(SH
),在这种情况下,目录名
只会返回。
(因为这是目录名
给出的参数,当没有的路径的分量)总是一样。命令-v - $ 0
然后返回通过$ PATH
查找(<$ C $ shell的绝对路径C> / bin / sh的)。但是请注意,该登录的在某些平台上(如OSX)弹有其名prefixed与-
在$ 1,0
(-SH
),在这种情况下,命令-v - $ 0
不作为工作打算(返回的空字符串的)。 - 相反,
命令-v - $ 0
可以在两种的不的-sourced方案中,胡作非为外壳可执行文件,SH
是直接的调用,用脚本作为参数:- 如果脚本本身的不的可执行文件:
命令-v - $ 0
可能返回的空字符串,这取决于具体的外壳作为SH
给定系统上:庆典
,KSH
和的zsh
返回一个空字符串;仅破折号
回声$ 1,0
结果
- 如果脚本的是的可执行文件,而不是在
$ PATH
,并调用使用它的只是文件名的(例如,SH myScript的
),命令-v - $ 0
也将返回的空字符串的,除了在破折号
。
- 如果脚本本身的不的可执行文件:
- 鉴于该脚本目录的不能的脚本时,被的来源确定的 - 因为
$ 1,0
则没有按' ŧ包含该信息(除的zsh
,它通常不会充当SH
) - 有没有很好的解决这个问题。- 返还的外壳可执行文件的的在这种情况下目录路径是有限的使用 - 它毕竟,不是的脚本的目录 - 除非是后来使用该路径一个的测试的决定的否的剧本正在采购。
- 系统更可靠的方法是简单地测试
$ 1,0
直接:[$ 0=SH] || [$ 0=-SH] || [$ 0=/ bin / sh的]
- 系统更可靠的方法是简单地测试
- 然而,即使如果该脚本是从来源不工作的其他的脚本(这是本身的直接的调用),因为
$ 0个
然后只需包含的采购的脚本的路径。
- 返还的外壳可执行文件的的在这种情况下目录路径是有限的使用 - 它毕竟,不是的脚本的目录 - 除非是后来使用该路径一个的测试的决定的否的剧本正在采购。
- 由于
命令-v的作用有限 - $ 0
在了源代码的场景和,它打破两个非的-sourced场景的事实我的票是不使用它,它留给我们:- 所有的不的-sourced场景是的覆盖。
- 在来源的调用,您的无法确定脚本的路径的,充其量,在有限的情况下,你可以的检测是否采购正在发生:
- 在当前采购的直接的由shell(如从壳型材/初始化文件),
$ DIR
结束或者包含。
,如果解释器可执行程序被调用作为一个单纯的文件名(适用目录名
来一个单纯的文件名的总是的返回。
),或在shell可执行文件的目录路径,否则。。
无法从当前目录中的非调用来源可靠地区分。 - 当来自的另一个脚本的(这是本身不是也提供),
$ 1,0
包含源的是的脚本的路径,与被采购的文字没有告诉这是否是该案件的方式。
- 在当前采购的直接的由shell(如从壳型材/初始化文件),
-
背景资料
POSIX 定义 $ 1,0
的的行为相对于外壳的脚本的 。
从本质上讲, $ 1,0
应反映在脚本文件的路径的为指定的的,这意味着:
- 不依赖于
$ 1,0
包含的绝对的路径 -
$ 1,0
包含一个的绝对的路径仅在- 您的明确的指定的绝对的路径;例如。:
-
〜/斌/ myScript的
(假设脚本本身是可执行的) -
SH〜/斌/ myScript的
-
- 您通过的只是文件名的,这就要求它既可执行的和的在
$ PATH
;在幕后,系统转换背后myScript的
成绝对路径,然后执行它;例如。:-
myScript的#执行时的/ home / JDOE /斌/ myScript的,比如
-
- 您的明确的指定的绝对的路径;例如。:
-
在其他情况下,
$ 1,0
将反映脚本的路径的为指定的的:- 当明确调用
SH
使用脚本,这可能是一个的只是文件名的(例如,SH myScript的
)或的相对路径的(例如,SH ./myScript
) - 当调用可执行脚本的直接的,这可能是一个的相对的路径(例如,
./ myScript的
- 注意,仅文件名的只会找到脚本的在$ PATH
的)。
- 当明确调用
在实践中, 庆典
,破折号
, KSH
和的zsh
都表现出这种行为。
相反, POSIX并不时的采购的脚本(使用特殊的内置强制 $ 1,0
的价值-in公用。
(点)),这样的你不能依靠它,然后在实践中,行为跨炮弹有所不同
- 因此,你不能盲目使用
$ 1,0
当你的脚本被采购,并期望行为规范。- 在实践中,
庆典
,破折号
和KSH
假$ 1,0
的触及采购脚本时,这意味着$ 1,0
包含的的的主叫方的的$ 1,0
值,或者更准确地说,最近调用链中调用者的$ 1,0
价值尚未来源本身;因此,$ 1,0
可能指向要么shell的可执行文件或到源的当前的其他的(直接援引)脚本的路径。 - 相反,
的zsh
,作为唯一的反对者,其实确实的在<$报告的电流的脚本的路径C $ C> $ 1,0 。相反,$ 1,0
将提供没有说明脚本是否正在采购或没有。 - 简而言之:使用POSIX才有的功能,你既不能告诉可靠手头的剧本是否正在来源,也没有什么手头的路径剧本,也没有什么关系
$ 1,0
当前脚本的路径。
- 在实践中,
- 如果您确实需要处理这种情况,您必须确定在现有的具体外壳和访问它的具体的非标准的特性:
-
庆典
,KSH
和的zsh
所有报价他们的的的获取运行脚本的路径方式,甚至当它被采购。
-
有关完整起见:在 $ 1,0
的值的其他的上下文
- 内壳的功能的,POSIX强制要求
$ 1,0
留的不变的;因此,无论价值具有的之外的功能,这将有在的为好。- 在实践中,
庆典
,破折号
和KSH
你的行为的方式。 - 同样,
的zsh
是唯一的反对者,并报告的函数的名称。
- 在实践中,
- 在接受通过
-c
选项命令字符串在启动一个空壳,它的的第一个操作数的(非选项参数),设置$ 1,0
;例如。:-
上海-c'回声\\ $ 0:$ 0 \\ $ 1:$ 1'foo的一个#, - &GT; '$ 0:foo的$ 1:一个人
-
庆典
,破折号
,KSH
和的zsh
所有行为的方式。
-
- ,否则后,在shell的不的执行的脚本文件的
$ 1,0
是第一个参数的值shell的的父进程的传递 - 通常情况下,这就是的壳牌的名称或路径(如SH
或/ bin / sh的
);这包括:- 的的交互的壳
- 买者:某些平台上,尤其是OSX,总是创建的登录的创建交互式的炮弹时,和贝壳的 prePEND
-
把它放置在$ 1,0
,以便发出信号,告知这是一个_login壳前壳EM>到shell名;因此,在默认情况下,$ 1,0
报告-bash
,而不是庆典
,在OSX交互式shell。
- 买者:某些平台上,尤其是OSX,总是创建的登录的创建交互式的炮弹时,和贝壳的 prePEND
- 一个shell读取的从命令的标准输入的
- 这也适用于通过标准输入到管道的脚本文件,在shell(例如,
SH&LT; myScript的
)
- 这也适用于通过标准输入到管道的脚本文件,在shell(例如,
-
庆典
,破折号
,KSH
和的zsh
所有行为的方式。
- 的的交互的壳
I have the following code in my bash script. Now I wanna use it in POSIX sh. So how to convert it? thanks.
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )"
The POSIX-shell (sh
) counterpart of $BASH_SOURCE
is $0
.
Caveat: The crucial difference is that if your script is being sourced (loaded into the current shell with .
), the snippets below will not work properly.
In the simplest case, this will do (the equivalent of the OP's command):
dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
If you also want to resolve the resulting directory path to its ultimate target in case the directory and/or its components are symlinks, add -P
to the pwd
command:
dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)
Caveat: This is NOT the same as finding the script's own true directory of origin:
Let's say your script foo
is symlinked to /usr/local/bin/foo
in the $PATH
, but its true path is /foodir/bin/foo
.
The above will still report /usr/local/bin
, because the symlink resolution (-P
) is applied to the directory, /usr/local/bin
, rather than to the script itself.
To find the script's own true directory of origin, you'd have to inspect the script's path to see if it's a symlink and, if so, follow the (chain of) symlinks to the ultimate target file, and then extract the directory path from the target file's canonical path.
GNU's readlink -f
(better: readlink -e
) could do that for you, but readlink
is not a POSIX utility.
In fact, there is no POSIX utility for resolving file symlinks.There are ways to work around that, but they're cumbersome and not fully robust:
The following, POSIX-compliant shell function implements what GNU's readlink -e
does and is a reasonably robust solution that only fails in two rare edge cases:
- paths with embedded newlines (very rare)
- filenames containing literal string
->
(also rare)
With this function, named rreadlink
, defined, the following determines the script's true directory path of origin:
dir=$(dirname -- "$(rreadlink "$0")")
rreadlink()
source code - place before calls to it in scripts:
rreadlink() ( # Execute the function in a *subshell* to localize variables and the effect of `cd`.
target=$1 fname= targetDir= CDPATH=
# Try to make the execution environment as predictable as possible:
# All commands below are invoked via `command`, so we must make sure that `command`
# itself is not redefined as an alias or shell function.
# (Note that command is too inconsistent across shells, so we don't use it.)
# `command` is a *builtin* in bash, dash, ksh, zsh, and some platforms do not even have
# an external utility version of it (e.g, Ubuntu).
# `command` bypasses aliases and shell functions and also finds builtins
# in bash, dash, and ksh. In zsh, option POSIX_BUILTINS must be turned on for that
# to happen.
{ \unalias command; \unset -f command; } >/dev/null 2>&1
[ -n "$ZSH_VERSION" ] && options[POSIX_BUILTINS]=on # make zsh find *builtins* with `command` too.
while :; do # Resolve potential symlinks until the ultimate target is found.
[ -L "$target" ] || [ -e "$target" ] || { command printf '%s\n' "ERROR: '$target' does not exist." >&2; return 1; }
command cd "$(command dirname -- "$target")" # Change to target dir; necessary for correct resolution of target path.
fname=$(command basename -- "$target") # Extract filename.
[ "$fname" = '/' ] && fname='' # !! curiously, `basename /` returns '/'
if [ -L "$fname" ]; then
# Extract [next] target path, which may be defined
# *relative* to the symlink's own directory.
# Note: We parse `ls -l` output to find the symlink target
# which is the only POSIX-compliant, albeit somewhat fragile, way.
target=$(command ls -l "$fname")
target=${target#* -> }
continue # Resolve [next] symlink target.
fi
break # Ultimate target reached.
done
targetDir=$(command pwd -P) # Get canonical dir. path
# Output the ultimate target's canonical path.
# Note that we manually resolve paths ending in /. and /.. to make sure we have a normalized path.
if [ "$fname" = '.' ]; then
command printf '%s\n' "${targetDir%/}"
elif [ "$fname" = '..' ]; then
# Caveat: something like /var/.. will resolve to /private (assuming /var@ -> /private/var), i.e. the '..' is applied
# AFTER canonicalization.
command printf '%s\n' "$(command dirname -- "${targetDir}")"
else
command printf '%s\n' "${targetDir%/}/$fname"
fi
)
To be robust and predictable, the function uses command
to ensure that only shell builtins or external utilities are called (ignores overloads in the forms of aliases and functions).
It's been tested in recent versions of the following shells: bash
, dash
, ksh
, zsh
.
As for how to handle sourced invocations:
tl;dr:
Using POSIX features only:
- You cannot determine the script's path in a sourced invocation (except in
zsh
, which, however, doesn't usually act assh
). - You can detect whether or not your script is being sourced ONLY if your script is being sourced directly by the shell (such as in a shell profile/initialization file; possibly via a chain of sourcings), by comparing
$0
to the shell executable name/path (except inzsh
, where, as noted$0
is truly the current script's path). By contrast (except inzsh
), a script being sourced from another script that itself was directly invoked, contains that script's path in$0
. - To solve these problems,
bash
,ksh
, andzsh
have nonstandard features that do allow determining the actual script path even in sourced scenarios and also detecting whether a script is being sourced or not; for instance, inbash
,$BASH_SOURCE
always contains the running script's path, whether it's being sourced or not, and[[ $0 != "$BASH_SOURCE" ]]
can be used to test whether the script is being sourced.
To show why this cannot be done, let's analyze the command from Walter A's answer:
# NOT recommended - see discussion below.
DIR=$( cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P )
- (Two asides:
- Using
-P
twice is redundant - it's sufficient to use it withpwd
. - The command is missing silencing of
cd
's potential stdout output, if$CDPATH
happens to be set.)
- Using
command -v -- "$0"
command -v -- "$0"
is designed to cover one additional scenario: if the script is being sourced from an interactive shell,$0
typically contains the mere filename of the shell executable (sh
), in which casedirname
would simply return.
(because that's whatdirname
invariably does when given a argument without a path component).command -v -- "$0"
then returns that shell's absolute path through a$PATH
lookup (/bin/sh
). Note, however, that login shells on some platforms (e.g., OSX) have their filename prefixed with-
in$0
(-sh
), in which casecommand -v -- "$0"
doesn't work as intended (returns an empty string).- Conversely,
command -v -- "$0"
can misbehave in two non-sourced scenarios in which the shell executable,sh
, is directly invoked, with the script as an argument:- if the script itself is not executable:
command -v -- "$0"
may return an empty string, depending on what specific shell acts assh
on a given system:bash
,ksh
, andzsh
return an empty string; onlydash
echoes$0
- if the script is executable, but not in the
$PATH
, and the invocation uses its mere filename (e.g.,sh myScript
),command -v -- "$0"
will also return the empty string, except indash
.
- if the script itself is not executable:
- Given that the script's directory cannot be determined when the script is being sourced - because
$0
then doesn't contain that information (except inzsh
, which doesn't usually act assh
) - there's no good solution to this problem.- Returning the shell executable's directory path in that situation is of limited use - it is, after all, not the script's directory - except perhaps to later use that path in a test to determine whether or not the script is being sourced.
- A more reliable approach would be to simply test
$0
directly:[ "$0" = "sh" ] || [ "$0" = "-sh" ] || [ "$0" = "/bin/sh" ]
- A more reliable approach would be to simply test
- However, even that doesn't work if the script is being sourced from another script (that was itself directly invoked), because
$0
then simply contains the sourcing script's path.
- Returning the shell executable's directory path in that situation is of limited use - it is, after all, not the script's directory - except perhaps to later use that path in a test to determine whether or not the script is being sourced.
- Given the limited usefulness of
command -v -- "$0"
in sourced scenarios and the fact that it breaks two non-sourced scenarios, my vote is for NOT using it, which leaves us with:- All non-sourced scenarios are covered.
- In sourced invocations, you cannot determine the script's path, and at best, in limited circumstances, you can detect whether or not sourcing is occurring:
- When sourced directly by the shell (such as from a shell profile/initialization file),
$dir
ends up either containing.
, if the shell executable was invoked as a mere filename (applyingdirname
to a mere filename always returns.
), or the shell executable's directory path otherwise..
cannot be reliably distinguished from a non-sourced invocation from the current directory. - When sourced from another script (that was itself not also sourced),
$0
contains that script's path, and the script being sourced has no way of telling whether that's the case.
- When sourced directly by the shell (such as from a shell profile/initialization file),
Background information:
POSIX defines the behavior of $0
with respect to shell scripts here.
Essentially, $0
should reflect the path of the script file as specified, which implies:
- Do NOT rely on
$0
containing an absolute path. $0
contains an absolute path only if:- you explicitly specify an absolute path; e.g.:
~/bin/myScript
(assuming the script itself is executable)sh ~/bin/myScript
- you invoke an executable script by mere filename, which requires that it both be executable and in the
$PATH
; behind the scenes, the system transformsmyScript
into an absolute path and then executes it; e.g.:myScript # executes /home/jdoe/bin/myScript, for instance
- you explicitly specify an absolute path; e.g.:
In all other cases,
$0
will reflect the script path as specified:- When explicitly invoking
sh
with a script, this can be a mere filename (e.g.,sh myScript
) or a relative path (e.g.,sh ./myScript
) - When invoking an executable script directly, this can be a relative path (e.g.,
./myScript
- note that a mere filename would only find scripts in the$PATH
).
- When explicitly invoking
In practice, bash
, dash
, ksh
, and zsh
all exhibit this behavior.
By contrast, POSIX does NOT mandate the value of $0
when sourcing a script (using the special built-in utility .
("dot")), so you cannot rely on it, and, in practice, behavior differs across shells.
- Thus, you cannot blindly use
$0
when your script is being sourced and expect standardized behavior.- In practice,
bash
,dash
, andksh
leave$0
untouched when sourcing scripts, meaning that$0
contains the caller's$0
value, or, more accurately, the$0
value of the most recent caller in the call chain that hasn't been sourced itself; thus,$0
may point either to the shell's executable or to the path of another (directly invoked) script that sourced the current one. - By contrast,
zsh
, as the lone dissenter, actually does report the current script's path in$0
. Conversely,$0
will provide no indication as to whether the script is being sourced or not. - In short: using POSIX features only, you can neither tell reliably whether the script at hand is being sourced, nor what the script at hand's path is, nor what the relationship of
$0
to the current script's path is.
- In practice,
- If you do need to handle this situation, you must identify the specific shell at hand and access its specific non-standard features:
bash
,ksh
, andzsh
all offer their own ways of obtaining the running script's path, even when it's being sourced.
For the sake of completeness: the value of $0
in other contexts:
- Inside a shell function, POSIX mandates that
$0
remain unchanged; therefore, whatever value it has outside the function, it'll have inside as well.- In practice,
bash
,dash
, andksh
do behave that way. - Again,
zsh
is the lone dissenter and reports the function's name.
- In practice,
- In a shell that accepted a command string via the
-c
option on startup, it's the first operand (non-option argument) that sets$0
; e.g.:sh -c 'echo \$0: $0 \$1: $1' foo one # -> '$0: foo $1: one'
bash
,dash
,ksh
, andzsh
all behave that way.
- Otherwise, in a shell not executing a script file,
$0
is the value of the first argument that the shell's parent process passed - typically, that's the shell's name or path (e.g.sh
, or/bin/sh
); this includes:- an interactive shell
- Caveat: some platforms, notably OSX, always create login shells when creating interactive shells, and prepend
-
to the shell name before placing it in$0
, so as to signal to the shell that it is a _login shell; thus, by default,$0
reports-bash
, notbash
, in interactive shells on OSX.
- Caveat: some platforms, notably OSX, always create login shells when creating interactive shells, and prepend
- a shell that reads commands from stdin
- this also applies to piping a script file to the shell via stdin (e.g.,
sh < myScript
)
- this also applies to piping a script file to the shell via stdin (e.g.,
bash
,dash
,ksh
, andzsh
all behave that way.
- an interactive shell
这篇关于如何让POSIX sh脚本目录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!