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).
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)?
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
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 -- *'
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
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.
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.
setopt extended_glob
(ou mesmo simplesrm * >/dev/null 2>&1
), mas realmente você deve fazer uma solução alternativa para não precisarrm *
, isso é outright perigoso/dev/null
vez dissodev/zero
. Além disso, seu redirecionamento stderr está ausente&
; deveria ser2>&1
.zsh
durante 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.Respostas:
Esse comportamento é controlado pela
nomatch
opçã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 executandoEm 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).fonte
nullglob
ecshnullglob
. Senullglob
estiver definido e nenhum arquivo correspondente for encontrado, o padrão será removido da lista de argumentos em vez de gerar um erro. A configuraçãocshnullglob
tem um efeito semelhante, a menos que todos os padrões em um comando não correspondam; nesse caso, um erro será relatado. Nota: configurandonullglob
oucshnullglob
substituindonomatch
. Você também pode definirnullglob
padrões individuais usando o qualificador globN
:rm *(N)
.nomatch
é menos que o ideal, é o que as conchas Bourne fazem. Se o padrão não corresponder, é passado como está pararm
(!), O querm
causará um erro, ou pior, poderá excluir o arquivo errado para um padrão como,*.[ch]
por exemplo!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)?files=(*(N)); (($#files)) && rm -- $files
. Ou(rm -- *) 2> /dev/null
mas isso também ocultaria erros genuínos pelosrm
quais seria tolo. Você pode descartar ozsh
erro, mas restaurar o stderr para orm
comando, embora com(rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
emulate sh -c 'rm -- *' 2> /dev/null
. Então, como nosh
qualzsh
agora emulado para essa linha de comando única, a não correspondência*
é passada como estárm
erm
reclama, pois esse*
arquivo não existe. Nós suprimimosrm
o stderr como você fariash
para suprimir essa mensagem de erro, mas, novamente, isso é bobagem, pois ocultaria erros genuínos porrm
oposição ao erro incorrido pelo mau comportamento desh
passar um literal*
pararm
.rm -f '*'
não iria reclamar de um*
arquivo inexistente , então você poderia fazeremulate sh -c 'rm -f -- *'
rm -- *(N)
.rm
reclamaria quando não fosse aprovado em nenhum argumento, porém novamenterm -f
: nãorm -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 orm
retorno. Você também geralmente deseja usar-f
scripts para evitar que o usuário seja solicitado em algumas situações.Aqui, telefonar
rm
quando o globo não corresponde está errado. O comportamentosh
1 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:Falhando com um erro é a coisa mais sensata a fazer e é o que
zsh
(efish
,csh
,tcsh
,bash -o failglob
e o shell do Unix original) faz.E se você quiser cuidar desse caso especial,
zsh
facilite 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 oset
comando. Então, o equivalente lá seria:Consulte Por que o nullglob não é o padrão para obter mais detalhes.
1 . A rigor, é apenas
sh
desde o shell Bourne (desde o Unix V7 em 1979); as versões anterioressh
(que chamavam/etc/glob
curingas não citados, de onde vem o nome do globo ) se comportavam comocsh
ouzsh -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.fonte
rm
e não do shell. Algo como "rm: não pode remover` * ': não existe esse arquivo ou diretório ".emulate sh -c 'rm -- *'
para obter o comportamento (IMO de buggy) do shell Bourne.rm
erros. 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.