在这种特殊情况下,我想在Bash中添加一个确认
Are you sure? [Y/n]
对于Mercurial的hg push ssh://用户名@www.example.com//somepath/morepath,这实际上是一个别名。是否有一个可以添加到别名的标准命令来实现它?
原因是hgpush和hgout听起来很相似,有时当我想要hgoutrepo时,我可能会意外地键入hgpushrepo(两者都是别名)。
更新:如果可以像内置命令一样使用另一个命令,比如:confirm && hg push ssh://…那太好了……只是一个命令,可以询问“是”或“否”,如果是则继续其余的操作。
这些是哈米什的回答中更紧凑、更通用的形式。它们可以处理任何大小写字母的混合:
read -r -p "Are you sure? [y/N] " response
case "$response" in
[yY][eE][sS]|[yY])
do_something
;;
*)
do_something_else
;;
esac
或者,对于Bash >= version 3.2:
read -r -p "Are you sure? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
then
do_something
else
do_something_else
fi
注意:如果$response是一个空字符串,它将给出一个错误。要修复,只需添加引号:"$response"。-在包含字符串的变量中总是使用双引号(例如:更喜欢使用“$@”而不是$@)。
或者,Bash 4.x:
read -r -p "Are you sure? [y/N] " response
response=${response,,} # tolower
if [[ "$response" =~ ^(yes|y)$ ]]
...
编辑:
作为对你的编辑的回应,以下是你如何根据我回答的第一个版本创建和使用确认命令(它将与其他两个类似):
confirm() {
# call with a prompt string or use a default
read -r -p "${1:-Are you sure? [y/N]} " response
case "$response" in
[yY][eE][sS]|[yY])
true
;;
*)
false
;;
esac
}
使用此函数:
confirm && hg push ssh://..
or
confirm "Would you really like to do a push?" && hg push ssh://..
在游戏后期,我创建了前面答案的确认函数的另一个变体:
confirm ()
{
read -r -p "$(echo $@) ? [y/N] " YESNO
if [ "$YESNO" != "y" ]; then
echo >&2 "Aborting"
exit 1
fi
CMD="$1"
shift
while [ -n "$1" ]; do
echo -en "$1\0"
shift
done | xargs -0 "$CMD" || exit $?
}
使用它:
confirm your_command
特点:
打印您的命令作为提示符的一部分
使用NULL分隔符传递参数
保留命令的退出状态
错误:
Echo -en与bash一起工作,但在shell中可能会失败
如果参数干扰echo或xargs,则可能失败
因为编写shell脚本很难,所以有无数的其他bug
我知道这是一个老问题,但这可能会帮助到一些人,它还没有在这里解决。
有人问我如何在接收文件输入的脚本中使用rm -i。由于脚本的文件输入通常是从STDIN接收的,因此我们需要更改它,以便从STDIN接收对rm命令的响应。下面是解决方案:
#!/bin/bash
while read -u 3 line
do
echo -n "Remove file $line?"
read -u 1 -n 1 key
[[ $key = "y" ]] && rm "$line"
echo
done 3<filelist
如果按下“y”键以外的任何键(仅限小写),文件将不会被删除。没有必要在键后按回车键(因此echo命令发送新行到显示器)。
请注意,POSIX bash“read”命令不支持-u开关,因此需要寻找解决方案。