Remover script de shell do Linux preso

2

Este script deve remover o conteúdo do diretório do caixote do lixo. Se a opção -a for usada, o script deve remover todos os arquivos da lixeira. Caso contrário, o script deve exibir os nomes dos arquivos na lixeira, um a um, e solicitar ao usuário a confirmação de que eles devem ser excluídos.

if test ! -f ~/TAM/dustbin/*
then
  echo "this directory is empty"
else
  for resfile in ~/TAM/dustbin/* 
  do
    if test -f $resfile ; then
      echo "Do you want to delete $resfile"
      echo "Y/N"
      read ans
      if test $ans = Y ; then 
        rm $resfile
        echo "File $resfile was deleted"
      fi
    fi
  done
fi

O que está acima está funcionando, no entanto, faz com que alguns erros sejam reportados mesmo embora ele ainda execute o código na próxima linha após o erro sem travar.

Erros:

./remove: line 4: test: to many arguments

(Isso acontece quando há mais de dois arquivos no lixo.)

./remove: line 4: test: root/TAM/dustbin/NewFile2: binary operator expected

(Isso acontece quando o arquivo é newfile2 mas não newfile3.)

Alguém também tem alguma opinião sobre como eu poderia fazer o -a para apagar tudo na pasta sem perguntar sobre cada arquivo separadamente?

    
por TAM 21.11.2012 / 12:11

3 respostas

1

Da primeira pergunta, basicamente, você está dando muitos parâmetros para o test lá (parece-me que a primeira linha do que você colou é na verdade a quarta linha do seu script). Se você tiver vários arquivos, você terá test -f file1 file2 file3… , enquanto test esperaria o operador binário (por exemplo, "-a" para AND) após -f file1 e a próxima expressão depois disso e assim por diante.

Quanto ao fornecimento e processamento dos parâmetros para o seu script excluir automaticamente os arquivos sem solicitar confirmação, você pode usar o mesmo test em $ 1 (este será o primeiro parâmetro de linha de comando do seu script).

    
por 21.11.2012 / 12:52
1

Você tem dois problemas principais.

O primeiro problema é o que acontece no primeiro comando: test ! -f ~/TAM/dustbin/* . Primeiro, o shell expande o padrão curinga ~/TAM/dustbin/* e, em seguida, passa a lista resultante para o comando test . Isso não funcionará se houver mais de um arquivo correspondente.

Com qualquer shell estilo Bourne, você pode salvar a lista de correspondências nos parâmetros posicionais e verificar se a primeira palavra existe (se isso não acontecer, o padrão não corresponde a nada).

set ~/TAM/dustbin/*
if ! test -f "$1"; then
  echo "this directory is empty"
…

(Veja esta resposta para formas de tornar um padrão de globalização não correspondente expandido para uma lista vazia em ksh, bash e zsh.

Observe que o diretório pode não estar vazio: ele pode conter arquivos de ponto (arquivos cujo nome começa com . , que o padrão curinga * ignora. Se você quiser verificar a existência de arquivos de ponto também, a maneira mais fácil de transportar é usar find :

if [ "$(cd ~/TAM/dustbin && find . | head -n 1)" = "." ]; then
  echo "this directory is empty"
else
  set ~/TAM/dustbin/..?* ~/TAM/dustbin/.[!.]* ~/TAM/dustbin/*
  for x; do
    if [ -f "$x" ]; then
      # $x is a regular file
    elif [ -e "$x" ]; then
      # $x is a directory or other special file
    else
      # $x is an unexpanded non-matching pattern
    fi
  done
fi

(Observe que test -f corresponde apenas a arquivos regulares; use -e para testar se existe um arquivo.)

Outro problema generalizado no seu script é que você não protege contra nomes de arquivos que contenham caracteres especiais do shell. Sempre use aspas duplas em torno das substituições de variáveis "$foo" e substituições de comandos "$(foo)" . Seu script pode sufocar ou remover o arquivo errado se um nome de arquivo contiver espaço em branco ou \[?* .

Eu assumo que este é um exercício de aprendizagem. Se não for:

#!/bin/bash
setopt nullglob
rm -ri ~/TAM/dustbin/*
    
por 22.11.2012 / 01:02
0
#!/bin/bash
dir="$HOME/TAM/dustbin"

# check if the dir is empty
shopt -s nullglob
files=("$dir"/*)
if (( ${#files[@]} == 0 )); then
    echo "the directory is empty"
    exit
fi

# handle command line arguments
all=false
while getopts :a opt; do
    case $opt in
        a) all=true ;;
        ?) echo "unknown option: -$OPTARG"; exit 1 ;;
    esac
done
shift $((OPTIND - 1))

# perform the deletion
if $all; then
    command rm "$dir"/*
else
    command rm -i "$dir"/*
fi
    
por 21.11.2012 / 12:52