Questão Como faço rm não dar um erro se um arquivo não existe?


Eu estou escrevendo um makefile que irá limpar alguns arquivos inúteis no final da compilação. Se um alvo já foi feito, ele obviamente pulará esse alvo e o arquivo inútil pode não estar lá. Então, se eu fizer isso:

rm lexer.ml interpparse.ml interpparse.mli

Eu posso pegar erros porque um dos arquivos não existe. Existe alguma maneira de dizer rm ignorar esses arquivos?

Ao ler a página man, 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.

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


261


origem


Você tentou alguma rm em uma caixa de areia? Parece que -f faz exatamente o que você quer, independentemente da globbing. - JMD
Se as permissões não permitirem, rm irá com o -f opção ainda tentar excluí-lo. Isso falhará. Não vai te dizer que falhou. Útil se o nome do arquivo for uma variável ou um glob. - LawrenceC


Respostas:


o -f opção é definitivamente o que você quer estar usando.

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'?

assim rm avisará se você tentar excluir um arquivo no qual não tenha permissões de gravação. Isso é permitido se você tiver permissões de gravação no diretório, mas é um pouco estranho, e é por isso rm normalmente avisa sobre isso.


221



A maioria, mas nem todos os sistemas perguntarão (eu acho). Alguns exigem -i. - DaveParillo
Se você quiser a mensagem de erro, mas não o código de saída de erro, veja a resposta Giel Berkers. eu uso set -e em todos os meus scripts de bash para que o script saia depois que qualquer comando der um erro. Muitas vezes eu quero um script para me dizer se rm deu um erro, mas continue assim mesmo. continuou. - cledoux


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

Desta forma, quando a instrução # 1 falhar (gera erro), execute a instrução # 2, que é simplesmente true.


77



Imprime o erro e continua a execução, o que foi desejado para o meu caso. - worldsayshi
Ou apenas rm -rf my/dir ||: ser ainda mais conciso (: é curto para true) - Godsmith
A melhor solução na minha opinião. É facilmente visível o que está acontecendo e porque o código de resultado é ignorado. Eu gosto disso! - Mavamaarten


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

-rm lexer.ml interpparse.ml interpparse.mli

69



Isso ainda imprimirá erro ao console, o que o leva a ignorar os erros na saída, o que provavelmente não é o que você deseja. rm -rf é uma opção melhor na minha opinião. - Godsmith
@Godsmith Eu prefiro ignorar um erro do que forçar a exclusão recursiva. Isso pode ser muito desobediente. E +1 para a sintaxe específica do makefile - Daishi
Se rm -rf puder ser "naughty", 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. Poderia encontrar uma descrição desse recurso. - George Sovetov
@GeorgeSovetov gnu.org/software/make/manual/make.html#Errors - Robert Li


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

rm filethatdoesntexist 2> /dev/null 

Isso apenas evitará que os erros sejam impressos.


8



Infelizmente isso ainda dará um código de saída de erro. - Shaun McDonald


Se você encontrar alguma maneira de glob os nomes dos arquivos, rm não vai reclamar se não conseguir encontrar uma correspondência. Então, algo como lexer.m* interpparse.*, etc. deve funcionar para você (tenha cuidado para não deletar demais, é claro). Além disso, -f é uma maneira perfeitamente razoável de ir, contanto que você não esteja esperando que as permissões de arquivo o salvem da exclusão de um arquivo que você não queria - se você não quiser excluí-lo, não o coloque no Lista.


7



O globbing estaria fora de questão, pois há um arquivo lexer.mll que não quero excluir. Obrigado por mostrar porque -f é razoável. Eu suponho que tendem a ser excessivamente cuidadosos depois de um excesso de sudo rm -rf . - Jason Baker
Nem mesmo um mais restritivo lexer.m? ...? Isso pegaria lexer.ml e lexer.mz, mas não lexer.mll ou lexer.mla. - JMD
@JMD: Suponho que isso depende do seu shell e do suporte de correspondência de padrões que ele oferece para globbing. - Nick Bastin


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

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. Esse é o caso quando você é o proprietário de um arquivo com permissões de somente leitura para o proprietário (-r --------). Como dono, você pode chmod u+we, em seguida, remova-o: rm -f irá remover esse arquivo.


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.


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 pode compartilhar definições de função de shell entre linhas.


2



Você tentou usar \ (barra invertida) no final de uma linha para continuar no próximo? - some
@alguma coisa: Sim, eles podem ser distribuídos em várias linhas, mas para compartilhá-los em receitas, você precisa colocar a definição em uma variável de criação. - reinierpost


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

2





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

touch lexer.ml interpparse.ml interpparse.mli
rm lexer.ml interpparse.ml interpparse.mli

0





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


0