如何获取 shell 脚本自身文件名?

2016-08-30 17:47:17 +08:00
 Devin
比如脚本 abc.sh ,在这个脚本里,如何获取自身文件名 abc.sh
13022 次点击
所在节点    Linux
22 条回复
bjzhou1990
2016-08-30 17:51:18 +08:00
$0
lxy42
2016-08-30 17:51:24 +08:00
echo $(basename $0)
Devin
2016-08-30 17:55:26 +08:00
@lxy42
@bjzhou1990
感谢,两种方法都可行
在这边如此容易的知识点,我找了好久 QAQ
lxy42
2016-08-30 18:08:57 +08:00
@Devin $0 是一个变量,保存了执行文件的文件名,相当于 C 语言中的 argv[0]
fool
2016-08-30 18:45:30 +08:00
楼上还不够完全正确

应该是 echo $BASH_SOURCE

如果是 $0 的话, source abc.sh 就会出错了
yaxin
2016-08-30 18:52:10 +08:00
还有一种情况$0 会出错,就是 cat abc.sh | bash
hasdream
2016-08-30 19:01:18 +08:00
一般 $(basename $0) 比如脚本在 /root 目录下 脚本名为 abc.sh 全路径运行 $0 是 /root/abc.sh 当前目录运行时 ./abc.sh basename 取最后一个文件名
wsy2220
2016-08-30 19:01:34 +08:00
如果是符号链接,$0 也不准
fiht
2016-08-30 21:02:59 +08:00
依楼上各位所言,确实没有一种很好的方法来确定脚本自身文件名。
其实原理很简单。
因为维度不一样, shell 脚本运行的时候是无法直接获得比自己高一维度的信息的。
就像虚拟机里面运行的程序不知道自己是在虚拟机里面跑一个道理
lrz0lrz
2016-08-30 21:40:21 +08:00
$ cat abc.sh
echo $0
echo $BASH_SOURCE
$ ./abc.sh
./abc.sh
./abc.sh
$ source abc.sh
bash
abc.sh
$ cat abc.sh |bash
bash

$ ~/temp/abc.sh
/home/xxx/temp/abc.sh
/home/xxx/temp/abc.sh
vus520
2016-08-30 22:28:05 +08:00
@lrz0lrz
SoloCompany
2016-08-31 00:07:02 +08:00
$0 是命令行里面的执行文件
${BASH_SOURCE[0]} 才是当前执行文件

比如命令行执行 0.sh 然后 0.sh 里面 include 1.sh
那么 1.sh 里面的 $0 对应的是 0.sh, ${BASH_SOURCE[0]} 才是 1.sh
Vicer
2016-08-31 01:25:29 +08:00
echo $0| awk -F "/" { print $NF }
没试过,不知有效不
Vicer
2016-08-31 01:28:02 +08:00
echo $0| awk -F "/" '{ print $NF }'
忘打引号了
jyf007
2016-08-31 06:44:37 +08:00
冒个泡,有道理啊。我调试 shell 实在麻烦。
clearbug
2016-08-31 07:05:47 +08:00
涨姿势。不过楼主获取自身文件名做什么?
GPU
2016-08-31 08:54:02 +08:00
realpath path/to/filename

这个也很有用 ,我也曾经找了很久.
wweir
2016-08-31 09:31:48 +08:00
给个建议,考虑这么多蛋疼的、少见的使用情形,不如直接来个来个运维规范。
只让 ./xxx.sh 来运行,一切不是都解决了吗?

当然,规范这事有时很难做,但是我们不是还可以引导么?
脚本开头统一 #!/bin/bash , 给出去就是一个带着 x 权限的没有后缀的文件。我想面对这样一个文件没多少人会敢直接 sh XXX 来瞎执行

PS :被各路运维 sh XXX.sh 搞得实在烦了,好端端的 bash 脚本,非要拿 dash / bash posix 模式来跑,不出错才怪。
araraloren
2016-08-31 11:12:35 +08:00
做了个测试


getname.sh:
#!/usr/bin/env bash

echo `basename $0`
echo `basename ${BASH_SOURCE}`

getname --> getname.sh , getname 是一个软链接

./getname | bash ./getname | sh ./getname

getname
getname

./getname.sh | bash ./getname.sh | ./getname.sh

getname.sh
getname.sh

source ./getname

bash
getname

source ./getname.sh

bash
getname.sh
extreme
2016-08-31 15:21:51 +08:00
C 的 argv[0],哈哈哈……


main.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void) {
char *argv[] = {"Hi, argv[0]", "argv[1]", NULL}, *env[] = {NULL};
if (execve("./print_argv_0", argv, env) < 0) {
perror("execve()");
return -1;
}
return 0;
}




print_argv_0.c:

#define _BSD_SOURCE

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
int pid = getpid();
char buffer[100], result_buffer[100];
printf("%s\n", argv[0]);
sprintf(buffer, "/proc/%d/exe", pid);
printf("%s\n", realpath(buffer, result_buffer));
return 0;
}


Example output:
user@hostname:/tmp$ /tmp/main
Hi, argv[0]
/tmp/print_argv_0

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/302728

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX