Como faço para que a rm não dê um erro se um arquivo não existe?

329

Estou escrevendo um makefile que irá limpar alguns arquivos inúteis no final da compilação. Se um destino já foi estabelecido, é claro que ele será ignorado e o arquivo inútil pode não estar lá. Então, se eu fizer isso:

rm lexer.ml interpparse.ml interpparse.mli

Posso receber erros porque um dos arquivos não existe. Existe alguma maneira de dizer rmpara ignorar esses arquivos?

Ao ler a página do manual, vejo a seguinte opção:

 -f          Attempt to remove the files without prompting for confirma-
             tion, regardless of the file's permissions.  If the file does
             not exist, do not display a diagnostic message or modify the
             exit status to reflect an error.  The -f option overrides any
             previous -i options.

Parece quase o que eu quero, mas não tenho muita certeza sobre a parte de permissões. Existe uma maneira de fazer isso?

Jason Baker
fonte
Você tentou alguns rmem uma caixa de areia? Parece que -ffaz exatamente o que você deseja, independentemente do globbing.
JMD
Se as permissões não permitirem, o rm -fainda tentará excluí-lo. Isso irá falhar. Não lhe dirá que falhou. Útil se o nome do arquivo for uma variável ou um glob.
LawrenceC
apenas para ser completo: existe algo rm --interactive=neverque age como, rm -fexceto que retorna um status de saída de erro. consulte aqui para obter mais detalhes: unix.stackexchange.com/questions/72864/…
lesmana

Respostas:

283

A -fopção é definitivamente o que você deseja usar.

A confirmação sobre as permissões de arquivo a que se refere é esta:

$ touch myfile    
$ chmod 400 myfile
$ rm myfile       
rm: remove write-protected regular empty file `myfile'?

Então rm, você será avisado se tentar excluir um arquivo no qual você não tem permissão de gravação. Isso é permitido se você tiver permissões de gravação no diretório, mas é um pouco estranho, e é por isso que rmnormalmente o alerta sobre isso.

Dave Webb
fonte
1
A maioria, mas nem todos os sistemas vão perguntar (eu acho). Alguns exigem -i.
31411 DaveParillo
1
Se você deseja a mensagem de erro, mas não o código de saída de erro, consulte a resposta de Giel Berkers . Eu uso set -eem todos os meus scripts bash para que o script saia após qualquer comando dar um erro. Geralmente, quero que um script me diga se rmocorreu um erro, mas continue assim mesmo. continuou.
Cledoux
124

Outra solução é esta: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

Basta adicionar uma instrução OR após o seu comando:

rm -rf my/dir || true

Dessa forma, quando a instrução nº 1 falhar (gera erro), execute a instrução nº 2, que é simples true.

Giel Berkers
fonte
4
Ele imprime o erro e continua a execução, o que foi desejado para o meu caso.
worldsayshi
9
Ou apenas rm -rf my/dir ||:para ser ainda mais concisa ( :é curto para true)
Godsmith
A melhor solução na minha opinião. É facilmente visível o que está acontecendo e por que o código do resultado é ignorado. Eu gosto disso!
Mavamaarten 03/10/19
76

Estou muito atrasado para a festa, mas uso isso o tempo todo. Em um makefile, adicione -ao início de uma linha para ignorar o valor de retorno dessa linha. Igual a:

-rm lexer.ml interpparse.ml interpparse.mli
Robert Li
fonte
9
No entanto, isso ainda imprime erro no console, que o treina para ignorar erros na saída make, o que provavelmente não é o que você deseja. rm -rf é uma opção melhor na minha opinião.
Godsmith
@ Godsmith Prefiro ignorar um erro do que forçar a exclusão recursiva. Isso pode ser muito travesso. E um para a sintaxe específica makefile
Daishi
Se rm -rf puder ser "impertinente", significa que você está usando make fora de um diretório sob controle de versão. Por quê?
Godsmith
Dê um link para a documentação, por favor. Pode encontrar a descrição desse recurso.
George Sovetov
14

Se você não quiser usar a opção -f, uma alternativa é:

rm filethatdoesntexist 2> /dev/null 

Isso evitará que erros sejam impressos.

user135299
fonte
9
Infelizmente, isso ainda dará um código de saída de erro.
Shaun McDonald
8

Se você encontrar uma maneira de divulgar os nomes dos arquivos, rmnão reclamará se não encontrar uma correspondência. Portanto, algo como lexer.m* interpparse.*etc. deve funcionar para você (tenha cuidado para não excluir muito, é claro). Além disso, -fé um caminho perfeitamente razoável, desde que você não espere que as permissões de arquivo o impeçam de excluir um arquivo que você não desejava - se você não quiser excluí-lo, não o coloque na lista.

Nick Bastin
fonte
O globbing estaria fora de questão, pois existe um arquivo lexer.mll que não quero excluir. Obrigado por mostrar por que -f é razoável. Suponho que sou muito cuidadoso depois de muitos desorientados sudo rm -rf.
27630 Jason Baker
Nem mesmo um mais restritivo lexer.m?...? Isso pegaria lexer.mle lexer.mz, mas não lexer.mllou lexer.mla.
JMD
1
@JMD: Suponho que depende do seu shell e de qual suporte de correspondência de padrões ele oferece para globbing.
22640 Nick Bastin
6

A opção -f significa que você não será solicitado se algo não for o esperado. Isso não significa que as permissões não sejam levadas em consideração.

Se você não tiver privilégios suficientes para remover um arquivo, ele não será removido.

MAS , se você tiver privilégios suficientes para alterar privilégios, seu arquivo será removido. É o caso de você ser o proprietário de um arquivo com permissões somente leitura para o proprietário (-r --------). Como proprietário, você pode chmod u+wremovê-lo: rm -fremoverá esse arquivo.

mouviciel
fonte
5

Talvez possa ajudar uma linha semelhante com:

touch fakefile.exe fakefile.o && rm *.o *.exe

Eu sei que isso não é muito inteligente, mas faz o trabalho.

Bogdan
fonte
3

Uma alternativa:

RmIfIsFile() {  for f in "$@"; do [ -f $f ] && rm $f; done; };  RmIfIsFile lexer.ml interpparse.ml interpparse.mli

Pena que Makefiles não podem compartilhar definições de funções de shell entre linhas.

reinierpost
fonte
Você tentou usar \ (barra invertida) no final de uma linha para permitir que ela continue na próxima?
alguns
@ Alguns: Sim, eles podem ser espalhados por várias linhas, mas para compartilhá-los entre as receitas, é necessário colocar a definição em uma variável make.
Reinierpost
3

Aqui está o que eu uso em scripts de shell. Ele oculta a mensagem de erro e o código de erro.

rm doesnotexist 2> /dev/null || echo > /dev/null
teh_senaus
fonte
que talrm doesnotexist 2&> /dev/null
user8162 18/02
1

você pode tocar nos arquivos antes de removê-los. que os criaria se eles não existirem :-)

touch lexer.ml interpparse.ml interpparse.mli
rm lexer.ml interpparse.ml interpparse.mli
commonpike
fonte
1

escreva rm -rf ppp>/dev/null 2>&1 você mais recente, obtenha mensagem de erro Problema ocorre, se o erro gerar não for STDERR 2, mas STDOUT 1 ... Ocorre quando o comando gera não erro, mas aviso. Você precisa definir o filtro e remover esta mensagem. Mas este caso é comum.

Anatoly
fonte
1

teste para ver se o arquivo existe primeiro, se existir, depois passe para rm. Os erros de rm serão significativos. -f ou ignorar a mensagem de erro é geralmente mais abrangente do que o que uma pessoa deseja. -f pode fazer coisas que você não quer que sejam feitas.

if [ -f lexer.ml ]; then
  rm lexer.ml
fi

adicione mais cláusulas de teste se houver mais arquivos que você deseja ter certeza de que existem.


fonte