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

21

Usando zsh, recebo a mensagem "Nenhuma correspondência encontrada" ao escolher um padrão que não se encaixa rme que mesmo ao redirecionar a saída.

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

Como posso me livrar dessa mensagem?

user123456
fonte
Você está tentando excluir tudo no diretório atual? Qual é o diretório atual?
Cutrightjm 17/09/16
Você pode usar setopt extended_glob(ou mesmo simples rm * >/dev/null 2>&1), mas realmente você deve fazer uma solução alternativa para não precisar rm *, isso é outright perigoso
grochmal
Você realmente deveria estar afundando em /dev/nullvez disso dev/zero. Além disso, seu redirecionamento stderr está ausente &; deveria ser 2>&1.
roaima 17/09/16
A mensagem de erro é gerada zshdurante a avaliação do comando e não durante o tempo de execução do próprio comando (devido ao erro, o comando nem mesmo é executado). Os redirecionamentos de saída aqui afetariam apenas a saída do comando e não o próprio shell.
Adaephon

Respostas:

41

Esse comportamento é controlado pela nomatchopção do Zsh . Por padrão, se uma linha de comando contiver uma expressão globbing que não corresponde a nada, o 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, expressões globbing que não correspondem a nada serão deixadas como estão e você receberá uma mensagem de erro rm(da qual você pode desativar o uso -f, embora seja uma má ideia, pois forçará remoções em outras situações em que você talvez não quer).

Stephen Kitt
fonte
4
O comportamento também é controlado pelas opções nullglobe cshnullglob. Se nullglobestiver definido e nenhum arquivo correspondente for encontrado, o padrão será removido da lista de argumentos em vez de gerar um erro. A configuração cshnullglobtem um efeito semelhante, a menos que todos os padrões em um comando não correspondam; nesse caso, um erro será relatado. Nota: configurando nullglobou cshnullglobsubstituindo nomatch. Você também pode definir nullglobpadrões individuais usando o qualificador glob N: rm *(N).
Adaephon 27/09/16
nomatché menos que o ideal, é o que as conchas Bourne fazem. Se o padrão não corresponder, é passado como está para rm(!), O que rmcausará um erro, ou pior, poderá excluir o arquivo errado para um padrão como, *.[ch]por exemplo!
Stéphane Chazelas
9

O que você gostaria que ele fizesse? Não é executado rm(1)? Executá-lo com um *argumento literal como em outros shells Bourne (2)? Executá-lo sem nenhum argumento (3)?

  1. files=(*(N)); (($#files)) && rm -- $files. Ou (rm -- *) 2> /dev/nullmas isso também ocultaria erros genuínos pelos rmquais seria tolo. Você pode descartar o zsherro, mas restaurar o stderr para o rmcomando, embora com(rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
  2. emulate sh -c 'rm -- *' 2> /dev/null. Então, como no shqual zshagora emulado para essa linha de comando única, a não correspondência *é passada como está rme rmreclama, pois esse *arquivo não existe. Nós suprimimos rmo stderr como você faria shpara suprimir essa mensagem de erro, mas, novamente, isso é bobagem, pois ocultaria erros genuínos por rmoposição ao erro incorrido pelo mau comportamento de shpassar um literal *para rm. rm -f '*'não iria reclamar de um *arquivo inexistente , então você poderia fazeremulate sh -c 'rm -f -- *'
  3. rm -- *(N). rmreclamaria quando não fosse aprovado em nenhum argumento, porém novamente rm -f: não rm -f -- *(N).

Geralmente, rm -fé o comando que você deseja usar se você deseja que todos os arquivos sejam removidos e só recebe um erro se os arquivos não puderem ser removidos ou o IOW ainda estiver lá após o rmretorno. Você também geralmente deseja usar -fscripts para evitar que o usuário seja solicitado em algumas situações.

Aqui, telefonar rmquando o globo não corresponde está errado. O comportamento sh1 está errado. É inofensivo para um padrão como *, mas para um exemplo *.[ch], passar *.[ch]como está quando não corresponde pode causar a *.[ch]remoção do arquivo 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

Falhando com um erro é a coisa mais sensata a fazer e é o que zsh(e fish, csh, tcsh, bash -o failglobe o shell do Unix original) faz.

E se você quiser cuidar desse caso especial, zshfacilite com o (N)qualificador glob (para noglob ) como no caso (1) acima. fish(pelo menos na versão recente ) facilita ainda mais, como faz um noglob implícito para o setcomando. Então, o equivalente lá seria:

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

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


1 . A rigor, é apenas shdesde o shell Bourne (desde o Unix V7 em 1979); as versões anteriores sh(que chamavam /etc/globcuringas não citados, de onde vem o nome do globo ) se comportavam como cshou zsh -o cshnullglob, isto é /etc/glob, interromperiam o comando se nenhum dos globs tivesse correspondência (e suprimiria os globs não correspondentes, se pelo menos um deles teve qualquer correspondência). O comportamento foi quebrado pelo shell Bourne.

Stéphane Chazelas
fonte
Eu acho que ele espera receber a mensagem de erro rme não do shell. Algo como "rm: não pode remover` * ': não existe esse arquivo ou diretório ".
Emmanuel
@Emmanuel, então esse é o 2: emulate sh -c 'rm -- *'para obter o comportamento (IMO de buggy) do shell Bourne.
Stéphane Chazelas
@Stephane_Chazelas como está escrito, 2 é a resposta certa para uma pergunta que ele não fez :).
Emmanuel
@Emmanuel, todos os três respondem à pergunta: como se livrar do erro "Não corresponde". O código do OP suprime os rmerros. Isso é algo que você faria em outros shells para suprimir o erro quando não há arquivo correspondente e que causa a supressão de erros rm genuínos. Minha resposta descreve isso e, espero, mostra como o comportamento zsh é preferível.
Stéphane Chazelas