Como verificar se existem vários arquivos?

Como verificar se existem vários arquivos?

Eu tenho um script de shell que procura um arquivo /tmp/bbsnode1e, se a existência desse arquivo for verdadeira, ele o exclui. O que eu gostaria de fazer é, se existirem vários arquivos ( /tmp/bbsnode2, /tmp/bbsnode3e /tmp/bbsnode4), excluir todos eles.Mas só exclua-os se todos existirem.

Aqui está o que tenho até agora:

if [ -f /tmp/bbsnode1 ]
then
/usr/bin/rm /tmp/bbsnode1
fi

Responder1

eu usaria uma conchafunçãopara isso, em vez de um script:

rm-all-or-none() {
  for f; do
    [ -f "$f" ] ||
      { printf '%s is not an existing file, no files removed\n' "$f" >&2
        return 1;}
  done
  rm -fv -- "$@"
}

Então eu chamaria isso de expansão de chaves, em vez de glob. Globs só se expandem para arquivos queexistir, mas neste caso queremos especificar os arquivos e removê-los apenas setodosdeles existem:

rm-all-or-none /tmp/bbsnode{1..4}

Versão equivalente mais longa:

rm-all-or-none() {
  for f in "$@"; do
    if [ -f "$f" ]; then
      :
    else
      printf '%s is not an existing file, no files removed\n' "$f" >&2
      return 1
    fi
  done
  rm -fv -- "$@"
}

Veja também:

Responder2

Você poderia usar um comando arbitrário, como lsverificar os arquivos e excluí-los em uma linha

ls /tmp/bbsnode{1,2,3,4} &>/dev/null && rm /tmp/bbsnode{1,2,3,4}

Observe que, em geral, não é seguro fazer essas coisas em /tmp porque qualquer outro usuário pode criar arquivos conflitantes com os mesmos nomes.

Uma breve explicação:

O valor de retorno de lsé diferente de zero se um dos arquivos não existir. A {1,2,3,4}expansão é entre chaves: ela se expande para uma string para cada número: então /tmp/bbsnode{1,2,3,4}é o mesmo que /tmp/bbsnode1 /tmp/bbsnode2 /tmp/bbsnode3 /tmp/bbsnode4. O &&executa o próximo comando somente se o comando anterior tiver um valor de retorno zero e, portanto, aqui rmsó é executado se todos os 4 arquivos existirem. Finalmente, &> /dev/nullsuprime a saída de ls( &>redirecionou ambos stdoute stderr, /dev/nulllivra-se dela).

Abaixo outra solução apenas com shell integrado. É semelhante ao que outros responderam, mas sem função ou script extra:

set -- /tmp/bbsnode{1,2,3,4}
(for f; do test -f "$f" || exit; done) && rm -- "$@"

Responder3

Neste caso específico você poderia fazer:

set -- file[1-4]
[[ $# -eq 4 ]] && rm -f -- "$@"

Esta seté a lista de argumentos para os nomes de arquivos que correspondem a qualquer um de file1, ou 1,file2 então esses arquivos serão apenas se o número de argumentos for igual a 4, ou seja, se todos os arquivos existirem. file3file4rm


1: para simplificar, uso fileem vez de/tmp/bbsnode

Responder4

Você poderia usar este script, chamadoremoving_group

#!/usr/bin/bash

function check {
    while (( "$#" )) ; do
        if [ -f "$1" ] ; then
            # echo "The file $1" ;
            shift ;
        else
            # echo "The's no file $1";
            return 1
        fi
    done
    return 0
}

if check $@; then
    while (( "$#" )) ; do
        # echo "Remove $1" ;
        rm "$1" ;
        shift ;
    done
fi

A checkfunção verifica se todos os seus argumentos são arquivos regulares. Se o próximo arquivo não existir, a função retorna 1e nada acontece. Se todos os arquivos existirem, o retorno 0será process if check $@, que removerá os arquivos um por um. Os arquivos para verificação e remoção descritos como parâmetros na linha de comando, por exemplo

./removing_group /tmp/bbsnode1 /tmp/bbsnode2 /tmp/bbsnode3 /tmp/bbsnode4

ou

./removing_group /tmp/bbsnode{1,2,3,4}

informação relacionada