我想编写一个脚本来访问交互式 bash shell 的状态,例如该脚本包含jobs
、dirs
、pushd
和等命令popd
。所以我的策略是source
当我运行脚本时将脚本放在shell中。但我经常忘记source
这一点,并一度感到困惑,这取决于我多久意识到这一点。是的,剧本是我自己写的。
那么对于像我这样健忘的人来说,有没有一些最佳实践呢?例如,以下任何一项是个好主意吗?
- 我们怎样才能在不输入的情况下运行脚本
source
,例如通过以某种方式修改脚本本身? 怎样才能让剧本本身让我想起
source
它呢?例如,- 使用前缀
Source_Me
?重命名脚本文件 - 或者脚本内部是否使用了一些命令来检测脚本是否被调用
source
,如果没有,则输出错误消息?
- 使用前缀
或者我应该更加努力地记住哪些脚本需要
source
?谢谢。
答案1
如果您获取它,则不需要执行位。
只是不要使脚本可执行。如果您随后尝试运行它(不获取它),它就不会运行 ( Permission denied
),因此不会发生任何效果。如果它在 PATH 环境中,具有完成功能的 shell (bash...) 甚至不会尝试使用 tab 自动完成它。
现在,您可以添加 in.profile
或.bashrc
类似的别名:
alias myscript='. /path/to/myscript'
因此,从现在开始,输入时myscript
将获取它并按预期运行它。 shell 甚至会自动完成别名。
答案2
如果您运行应该是源代码的脚本,则可以使用几种策略来打印错误消息。
您可以检查是否
$0
与您的脚本名称相对应;如果是,则说明它没有被获取,因此打印一条错误消息并退出:if [ "${0##*/}" = "myscript" ]; then echo "Don't run me, source me" >&2 exit 1 fi
(然后,每当您的脚本重命名时,您都需要注意更新...)
一种变体可能是检查
$0
的内容/etc/shells
,如果这是可接受的限制(IE您的 shell 脚本仅使用此处列出的 shell 运行,这绝不是一种义务)。如果您的脚本仅打算在交互式 shell 中使用,您可以检查这一点 - 如果它是运行而不是被获取,则它不会在交互式 shell 中:
case "$-" in *i*) ;; *) echo "Don't run me, source me" >&2; exit 1 ;; esac
答案3
怎样才能让剧本本身让我想起
source
它呢?
创建自定义解释器source_reminder
并使其可执行:
#!/bin/sh
printf "%s\n" "Source me!" >&2
exit 1
然后只需在可执行脚本中使用它:
#!/path/to/your/source_reminder
foo
bar
whatever
现在,如果您在没有源的情况下运行脚本,提醒将发挥作用。
在我的 Debianprintf
本身中可以用作基本提醒:
#!/usr/bin/printf Source me! . %q\n
foo
bar
whatever
但自然地,当以这种方式使用时,它会打印到标准输出并成功退出。
答案4
它必须是源脚本吗?让它成为一个函数。所以而不是
$ . something some args # run it
有
$ cat define_something.sh
something() {
commands here...
}
$ . define_something.sh # load the function definition
$ something some args # run the function
或者,如果您希望实际命令位于源脚本中,请使用一个函数来获取它:
something() {
. something "$@"
}
然后运行something foo bar
而不是. something foo bar
.
当然,函数隐藏了主 shell 环境的位置参数,因此这在那里不起作用。如有必要,也许可以使用别名 from something
。. something
(这已经由他们的答案中的AB.)