Como se livrar de "Nenhuma correspondência encontrada" ao executar "rm *"

9

Usando zsh , recebo uma mensagem "Nenhum resultado encontrado" ao escolher um padrão que não cabe no rm e que, mesmo quando redirecionando a saída.

# rm * > /dev/zero 2>&1
  zsh: no matches found: *

Como posso me livrar dessa mensagem?

    
por user123456 17.09.2016 / 20:00

2 respostas

15

Esse comportamento é controlado pela nomatch option do Zsh. Por padrão, se uma linha de comando contiver uma expressão globbing que não corresponde a nada, Zsh imprimirá a mensagem de erro que você está vendo e não executará o comando. Você pode desativar isso executando

setopt +o nomatch

Em seguida, as expressões de globbing que não corresponderem a nada serão deixadas como estão, e você receberá uma mensagem de erro de rm (que pode ser desabilitada usando -f , embora seja uma má ideia, pois forçar remoções em outras situações em que você pode não querer).

    
por 17.09.2016 / 21:03
5

O que você gostaria de fazer? Não execute rm (1)? Execute-o com um argumento literal * como em outras shells parecidas com Bourne (2)? Execute-o sem nenhum argumento (3)?

  1. %código%. Ou files=(*(N)); (($#files)) && rm -- $files , mas isso também esconderia erros genuínos por (rm -- *) 2> /dev/null , o que seria tolo. Você pode descartar o erro rm , mas restaurar o stderr para o comando zsh , embora com rm
  2. %código%. Então, como em (rm -- * 2>&3 3>&-) 3>&2 2> /dev/null que emulate sh -c 'rm -- *' 2> /dev/null agora emulado para aquela única linha de comando, o sh não correspondente é passado como é para zsh e * reclama como se o arquivo rm não existisse. Nós suprimimos o stderr de rm como você faria em * para suprimir essa mensagem de erro, mas novamente, isso é bobagem pois esconderia erros genuínos por rm em oposição ao erro incorrido pelo mau comportamento de sh passando um literal rm para sh . No entanto, * não se queixaria de um arquivo rm inexistente, portanto você poderia fazer rm -f '*'
  3. %código%. * reclamaria quando não passasse nenhum argumento, embora, novamente, não emulate sh -c 'rm -f -- *' : rm -- *(N) .

Geralmente, rm é o comando que você deseja usar se quiser que todos os arquivos desapareçam e só recebam um erro se os arquivos não puderem ser removidos ou se o IOW ainda estiver lá após rm -f ter retornado. Você também geralmente deseja usar rm -f -- *(N) em scripts para evitar que o usuário seja solicitado em algumas situações.

Aqui, chamar rm -f quando o glob não combina está errado. O comportamento rm 1 está errado. É inofensivo para um padrão como -f , mas para um como rm , passar sh como está quando não corresponde pode fazer com que o arquivo * seja removido por engano:

$ ls
*.[ch]  foo.txt
$ zsh -c 'rm *.[ch]'
zsh:1: no matches found: *.[ch]
$ ls
*.[ch]  foo.txt
$ sh -c 'rm *.[ch]'
$ ls
foo.txt

A falha com um erro é a coisa mais sensata a fazer e é o que o *.[ch] (e *.[ch] , *.[ch] , zsh , fish e o shell original do Unix) faz.

E se você quiser cuidar desse caso especial, csh torna mais fácil o seu qualificador tcsh glob (para noglob ) como no caso (1) acima. bash -o failglob (pelo menos na versão recente ) torna isso ainda mais fácil, já que faz uma implícita < em> noglob para o comando zsh . Então, o equivalente lá seria:

set files *
if count $files > /dev/null
  rm -f -- $files
end

Veja Por que o nullglob não é o padrão para mais detalhes.

1 . Estritamente falando, é apenas (N) desde o shell Bourne (desde o Unix V7 em 1979); versões anteriores de fish (que chamaram set sobre curingas não nomeadas, de onde vem o nome glob ) se comportaram como sh ou sh , ou seja, /etc/glob iria abortar o comando se nenhum dos globs tivesse qualquer correspondência (e suprimiria os globs não correspondentes se pelo menos um deles tivesse alguma correspondência). O comportamento foi quebrado pela shell Bourne.

    
por 29.09.2016 / 14:49