Função com muitos argumentos, mas apenas um switch

2

Estou efetivamente fazendo uma lixeira através de alguns scripts que fiz.

O primeiro script é praticamente uma alternativa ao comando rm (em vez de excluir um arquivo, ele é movido para uma pasta excluída).

Eu consegui permitir que o script movesse vários arquivos para a pasta excluída:

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

O início do meu primeiro roteiro é:

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

Um por um, cada parâmetro (arquivo) é movido para a pasta excluída. Agora estou tentando incorporar parâmetros de comutação, mas não tenho certeza de como incorporar isso.

O acima funciona para sh moveToBin file1 file2 file3 mas como eu incorporo a possibilidade de que o primeiro argumento (somente o primeiro) PODERIA ser um comutador -i (pedir para excluir), -v (confirmar exclusão), -iv (peça para excluir e confirme a exclusão).

Assim, o comutador só se aplica a $1 . Eu tentei algo chamado getopts, mas não estou familiarizado com o uso. Depois que um switch é usado, isso se aplica a $2 onwards, por exemplo,

sh moveToBin -i file1 file2

isto pede para deletar file1, e depois que eu decido, ele pede para deletar file2 Pensei em algo assim, mas duvido que funcione. alguma ajuda?

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

A condição while loop significa que é o primeiro parâmetro e que esse parâmetro inicia com um hífen.

    
por user3120554 20.08.2015 / 23:38

2 respostas

3

O getopts incorporado analisa as opções. Você o executa apenas uma vez para todas as opções e, em seguida, processa os operandos (argumentos não opcionais) que restam. getopts permite ao chamador escrever com indiferença, por ex. moveToBin -iv file1 ou moveToBin -i -v file1 , e você pode escrever moveToBin -- -file para manipular nomes de arquivos que começam com um traço (qualquer coisa depois que -- for interpretado como um operando).

getopts registra quantos argumentos já foram processados por meio da variável OPTIND . Quando terminar seu trabalho, OPTIND é o índice do primeiro operando; como os argumentos são numerados de 1, isso significa que os primeiros OPTIND-1 argumentos eram opções.

Desde que você esteja analisando as opções, ainda não sabe a lista de arquivos a serem processados. Então lembre-se da opção definindo uma variável e consulte a variável mais tarde.

#!/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

Observe que getopts segue o modelo de análise de opção tradicional, em que qualquer coisa após o primeiro operando é uma não opção. Em outras palavras, em moveToBin -i foo -v bar , há a opção -i e, em seguida, três arquivos foo , -v e bar . Se você quiser permitir o modelo de análise de opções GNU, onde as opções podem ser misturadas com operandos, getopts não é particularmente útil. Nem o getopts do bash pode analisar as opções longas do GNU ( --verbose seria analisado como -v -e -r -b -o -s -e mais um erro sobre - não suportado).

    
por 21.08.2015 / 00:03
0
#!/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

E depois do habitual chmoddery e outras coisas:

$ ./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
$ 
    
por 21.08.2015 / 00:03