发出控制脚本流程

时间:2012-12-03 11:58:43

标签: linux shell scripting

我是shell脚本的新手,我的脚本似乎没问题,但是我正在控制问题。有人能指出我做出的愚蠢错误。

#! /bin/sh

echo "Are you sure youx want to delete $1? Answer y or n"
read ans
echo $ans
if $ans = "y"|"Y"
then
    mv $1 /home/parallels/dustbin
    echo "File $1 has been deleted"
else echo "File $1 has not been deleted"
fi

4 个答案:

答案 0 :(得分:1)

制作你喜欢的if条件:

if [ "$ans" = "y" -o "$ans" = "Y" ]

答案 1 :(得分:1)

您的脚本有一些问题。有些是严肃的,有些则不那么严重。

首先是严重的问题。

正如大师建议的那样,您需要使用方括号来包围if条件。这是因为if仅测试条件的输出,它不执行实际的字符串比较。传统上,名为/bin/test的程序(也称为/bin/[)负责处理此问题。目前,该功能内置于shell中,但/bin/sh仍然表现得像是一个单独的程序。

事实上,当您使用方括号表示条件时,您可以使用if执行有趣的操作。例如,if grep -q 'RE' /path/to/file; then很常见。 grep -q命令不发出输出,只返回if检测到的“成功”或“失败”。

第二个严重问题是你回应的状态可能是也可能不是。我称这是一个严重的问题,因为......好吧,日志消息根本不应该做出错误的声明。如果$1中的文件的权限错误,或者文件名包含空格,则您的mv命令将失败,但该消息将声明它没有。稍后会详细介绍。

接下来,问题不那么严重了。

这些主要是风格和优化的东西。

首先,大多数平台上的read都包含-p选项,可让您指定提示。使用此选项,您不需要包含echo命令。

其次,你的缩进使得很难看到if构造包装的内容。这对于这么小的程序来说不是一个大问题,但随着你的成长,你真的想要遵循一致的标准。

第三,如果您使用case语句而不是if,则可以在选择性问题中获得更大的灵活性。

毕竟,这就是我写这个脚本的方式:

#!/bin/sh

if [ "$1" = "-y" ]; then
  ans=y
  shift
elif [ -t 0 ]; then
  read -p "Are you sure you want to delete '$1' (y/N) ? " ans
fi

case "$ans" in
  Y*|y*)
    retval=0
    if [ -z "$1" ]; then
      retval=64
      echo "ERROR: you didn't specify a filename." >&2
    if [ ! -f "$1" ]; then
      retval=66
      echo "ERROR: file '$1' not found!" >&2
    elif mv "$1" /home/parallels/dustbin/; then
      echo "File '$1' has been deleted" >&2
    else
      retval=$?
      echo "ERROR: file '$1' could not be deleted!" >&2
    fi
    ;;
  *)
    echo "ABORT: file '$1' has not been deleted" >&2
    retval=4
    ;;
esac

exit $retval

除了上面提到的内容之外,以下是此代码段中的一些内容:

  • [ "$1" = "-y" ] - 如果用户指定-y选项,那么我们的行为就好像问题的回答是“是”。
  • [ -t 0 ] - 这会测试我们是否在互动终端上。如果我们是,那么用read提问是有意义的。
  • Y*|y*) - 在case语句中,匹配任何以大写或小写“y”开头的字符串。因此,有效的肯定回答将是“Y”,“是”,“黄色”等。
  • [ ! -f "$1" ] - 测试文件是否存在。您可以man testman sh查看shell中可用的各种测试。 (-f可能不适合您。)
  • >&2 - 在一行的末尾,将其输出发送到“标准错误”而不是“标准输出”。这会改变管道,cron等处理输出的方式。错误和日志数据通常会发送到stderr,因此stdout可以专用于程序的实际输出。
  • mv "$1" ... - 文件名用引号括起来。如果文件名中包含空格等特殊字符,这可以保护您。
  • $retval - 此值来自对man sysexits中最近项的最佳猜测。
  • retval=$? - 这是最近执行的命令的退出状态。在这种情况下,这意味着我们将mv的退出状态分配给变量$retval,这样如果mv失败,整个脚本会报告失败的原因,目前为止与mv有关。

答案 2 :(得分:0)

您还可以将用户响应转换为任何一种情况,只需检查相应的情况,如

read ans
ans=${ans,,}  # make 'ans' lowercase, or use ${ans^^} for making it uppercase
if [ "$ans" = "y" ]
then
   ....
fi

答案 3 :(得分:0)

以下是包含错误处理的完美代码

#!/bin/sh

echo "Are you sure you want to delete $1? Answer y or n"
read ans
echo $ans

if [ $ans == "y" ] || [ $ans == "Y" ]
then
    if [ -f $1 ]
    then
           mv $1 /home/parallels/dustbin
           echo "File $1 has been deleted"         
    else
           echo " File $1 is not found"
    fi
else 
    echo "File $1 has not been deleted"
fi