忘记使用“source”运行脚本的策略?

忘记使用“source”运行脚本的策略?

我想编写一个脚本来访问交互式 bash shell 的状态,例如该脚本包含jobsdirspushd和等命令popd。所以我的策略是source当我运行脚本时将脚本放在shell中。但我经常忘记source这一点,并一度感到困惑,这取决于我多久意识到这一点。是的,剧本是我自己写的。

那么对于像我这样健忘的人来说,有没有一些最佳实践呢?例如,以下任何一项是个好主意吗?

  1. 我们怎样才能在不输入的情况下运行脚本source,例如通过以某种方式修改脚本本身?
  2. 怎样才能让剧本本身让我想起source它呢?例如,

    • 使用前缀Source_Me?重命名脚本文件
    • 或者脚本内部是否使用了一些命令来检测脚本是否被调用source,如果没有,则输出错误消息?
  3. 或者我应该更加努力地记住哪些脚本需要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.)

相关内容