具有多个参数但只有一个开关的函数

具有多个参数但只有一个开关的函数

我正在通过我制作的一些脚本有效地制作一个回收站。

第一个脚本几乎是 rm 命令的替代方案(它不是实际删除文件,而是将其移动到已删除的文件夹)。

我已设法允许脚本将多个文件移动到已删除的文件夹:

sh moveToBin file1 file2 fil3 (similar to: rm file1 file2 file3)

我的第一个脚本的开头是:

#!/bin/bash
for param in "$@"
do
..
..
(main part of my code)

将每个参数(文件)一一移至已删除的文件夹中。我现在正在尝试合并添加 switch 参数,但我不太确定如何合并它。

上面的方法适用sh moveToBin file1 file2 file3,但我如何合并第一个参数(仅第一个)可以是开关-i(要求删除)、-v(确认删除)、-iv(要求删除然后确认删除)的可能性。

因此该开关仅适用于$1.我尝试了一个叫做 getopts 的东西,但我不熟悉它的用法。一旦使用开关,这适用于$2以后的情况,即

sh moveToBin -i file1 file2

这要求删除 file1,在我决定之后,它会要求删除 file2 我想到了类似的东西,但我怀疑它是否会起作用。有什么帮助吗?

counter=1
for param in "$@"
do
       while [[ if $param = "-*" && counter -eq1]];
       do 
              getopts "iv" arg;
              case "$arg" in
                  i) read -p "want to delete $param ?" ans
                     if [ ans =~ ^[Y][y] ] 
                     then 
                          #run main code for that param value              
                     fi;;
                  v) #run main code for that param value 
                     echo "file @param deleted";;
              esac
              counter=$((counter+1))
              continue
       done

      #run main code for that param value
done

while循环条件意味着它是第一个参数并且该参数以连字符开头。

答案1

内置getopts解析选项。您只需对所有选项运行一次,然后处理剩下的操作数(非选项参数)。getopts允许调用者随意编写例如moveToBin -iv file1moveToBin -i -v file1,并且您可以编写moveToBin -- -file处理以破折号开头的文件名(后面的任何内容--都被解释为操作数)。

getopts跟踪已经通过OPTIND变量处理了多少个参数。当它完成它的工作时,OPTIND是第一个操作数的索引;由于参数从 1 开始编号,这意味着第一个OPTIND-1参数是选项。

只要您正在解析选项,您就不知道要处理的文件列表。因此通过设置变量来记住该选项,并稍后查询该变量。

#!/bin/bash
confirm=
verbose=
while getopts 'iv' OPTLET; do
  case $OPTLET in
    i) confirm=y;;
    v) verbose=y;;
    \?) exit 3;;  # Invalid option; getopts already printed an error message
  esac
done
shift $((OPTIND-1))

for file in "$@"; do
  if [[ -n $confirm ]]; then
    read -p "want to delete $param ?" ans
    if [[ $ans != [Yy]* ]]; then
      continue       # the user said no, so skip this file
    fi
  fi
  … # do that moving stuff
  if [[ -n $verbose ]]; then
    echo "File $file deleted"
  fi
done

请注意,getopts遵循传统的选项解析模型,其中第一个操作数之后的任何内容都是非选项。换句话说,在 中moveToBin -i foo -v bar,有-i选项,然后是三个文件foo-vbar。如果您想允许 GNU 选项解析模型(其中选项可以与操作数混合),getopts则不是特别有帮助。 bash 的getopts内置解析 GNU 长选项也无法解析(--verbose会像-v -e -r -b -o -s -e加上不支持的错误一样进行解析-)。

答案2

#!/usr/bin/env bash

VERBOSE=n

while getopts "vC:" opt; do
  case $opt in
    v)
      VERBOSE=y
      ;;
    C)
      echo got $OPTARG
      ;;
  esac
done
shift $(($OPTIND - 1))

echo "soooo verbose is $VERBOSE"

for x in "$@"; do
  echo "still got: $x"
done

然后在通常的 chmoddery 之类的之后:

$ ./gopt hi there
soooo verbose is n
still got: hi
still got: there
$ ./gopt -v hi there
soooo verbose is y
still got: hi
still got: there
$ ./gopt -C cats -v hi there
got cats
soooo verbose is y
still got: hi
still got: there
$ 

相关内容