
Eu tenho um script de shell que procura um arquivo /tmp/bbsnode1
e, 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/bbsnode3
e /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 ls
verificar 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 rm
só é executado se todos os 4 arquivos existirem. Finalmente, &> /dev/null
suprime a saída de ls
( &>
redirecionou ambos stdout
e stderr
, /dev/null
livra-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. file3
file4
rm
1: para simplificar, uso file
em 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 check
função verifica se todos os seus argumentos são arquivos regulares. Se o próximo arquivo não existir, a função retorna 1
e nada acontece. Se todos os arquivos existirem, o retorno 0
será 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}