【发布时间】:2018-07-12 09:07:47
【问题描述】:
问题是:我有这个脚本foo.py,如果用户在没有--bar 选项的情况下调用它,我想显示以下错误消息:
Please add the --bar option to your command, like so:
python foo.py --bar
现在,棘手的部分是用户可能会通过多种方式调用命令:
- 他们可能使用了
python foo.py,就像示例中一样 - 他们可能使用过
/usr/bin/foo.py - 他们可能有一个shell别名
frob='python foo.py',实际上运行frob - 也许它甚至是一个git别名
flab=!/usr/bin/foo.py,而他们使用git flab
在每种情况下,我都希望消息能够反映用户如何调用命令,以便我提供的示例有意义。
sys.argv 总是包含foo.py,而/proc/$$/cmdline 不知道别名。在我看来,此信息的唯一可能来源是 bash 本身,但我不知道如何询问。
有什么想法吗?
更新如果我们将可能的场景限制在上面列出的那些呢?
更新 2:很多人写了很好的解释说明为什么在一般情况下这是不可能的,所以我想把我的问题限制在这个:
在以下假设下:
- 脚本以交互方式从 bash 启动
- 脚本以以下三种方式之一之一启动:
-
foo <args>其中 foo 是符号链接 /usr/bin/foo -> foo.py -
git foowhere alias.foo=!/usr/bin/foo in~/.gitconfig -
git baz其中 alias.baz=!/usr/bin/foo 在~/.gitconfig
-
有没有办法从脚本中区分 1 和 (2,3)?有没有办法从脚本中区分 2 和 3?
我知道这是一个很长的机会,所以我现在接受 Charles Duffy 的回答。
更新 3:到目前为止,最有希望的角度是 Charles Duffy 在下面的 cmets 中提出的。如果我能让我的用户拥有
trap 'export LAST_BASH_COMMAND=$(history 1)' DEBUG
在他们的.bashrc 中,然后我可以在我的代码中使用这样的东西:
like_so = None
cmd = os.environ['LAST_BASH_COMMAND']
if cmd is not None:
cmd = cmd[8:] # Remove the history counter
if cmd.startswith("foo "):
like_so = "foo --bar " + cmd[4:]
elif cmd.startswith(r"git foo "):
like_so = "git foo --bar " + cmd[8:]
elif cmd.startswith(r"git baz "):
like_so = "git baz --bar " + cmd[8:]
if like_so is not None:
print("Please add the --bar option to your command, like so:")
print(" " + like_so)
else:
print("Please add the --bar option to your command.")
这样,如果我无法获得他们的调用方法,我会显示一般消息。当然,如果我要依靠更改用户的环境,我不妨确保各种别名导出自己可以查看的环境变量,但至少这种方式允许我对任何使用相同的技术稍后我可能会添加其他脚本。
【问题讨论】:
-
也许
history 1就够了吗? -
如果
--bar是强制性的,那么总是自己在内部添加它,并为不想要它但知道如何添加参数的更熟练的用户提供--no-bar怎么样?跨度> -
@MarkSetchell 我的概括性尝试在这里适得其反。我当前的用例是关于一个退出的脚本,但想告诉用户他们可以继续使用--continue。有点像
git rebase遇到冲突时。所以你的想法对我不起作用。 -
而不是在如何找到调用的名称上浪费很多周期(恕我直言,有很多极端情况会失败)——为什么不处理给用户的消息?
Please add the --bar option to your command, like so: 'cmd --bar'大多数人都很聪明(再说一遍,恕我直言)知道cmd是他们输入的任何内容的填写。 -
请注意,有可能使 shell 从
DEBUG陷阱中将BASH_COMMAND的副本导出到环境中,但如果您依赖它,您的程序只有在被如此准备好的 shell 调用时才会有手头的行为......所以它看起来几乎没有用。
标签: linux bash command-line-interface