Come faccio a fare in modo che rm non dia un errore se non esiste un file?


329

Sto scrivendo un makefile che pulirà alcuni file inutili alla fine della compilation. Se un target è già stato creato, ovviamente salterà quel target e il file inutile potrebbe non essere lì. Quindi se lo faccio:

rm lexer.ml interpparse.ml interpparse.mli

Potrei ricevere errori perché uno dei file non esiste. C'è un modo per dire rmdi ignorare questi file?

Nella lettura della pagina man, vedo la seguente opzione:

 -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.

Sembra quasi quello che voglio, ma non sono davvero sicuro della parte dei permessi. C'è un modo per fare questo?


Ne hai provato un po ' rmin una sandbox? Sembra che -ffaccia esattamente quello che vuoi, indipendentemente dal travolgimento.
JMD,

Se i permessi non lo permetteranno, rm tenterà ancora con l' -fopzione di eliminarlo. Fallirà. Non ti dirà che è fallito. Utile se il nome file è una variabile o un glob.
LawrenceC,

solo per completezza: c'è rm --interactive=neverche si comporta come rm -fse non restituisse uno stato di uscita dell'errore. vedi qui per maggiori dettagli: unix.stackexchange.com/questions/72864/…
lesmana

Risposte:


283

L' -fopzione è sicuramente ciò che si desidera utilizzare.

La conferma delle autorizzazioni per i file a cui fa riferimento è questa:

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

Quindi rmti avvertirò se provi a eliminare un file per il quale non hai i permessi di scrittura. Ciò è consentito se si dispone di autorizzazioni di scrittura sulla directory, ma è un po 'strano, motivo per cui rmnormalmente ti avverte al riguardo.


1
La maggior parte, ma non tutti i sistemi chiederanno (penso). Alcuni richiedono -i.
DaveParillo,

1
Se si desidera il messaggio di errore, ma non il codice di uscita dell'errore, vedere la risposta di Giel Berkers . Uso set -etutti i miei script bash in modo che lo script esca dopo che un comando ha dato un errore. Spesso voglio uno script che mi dica se ha rmdato un errore, ma continua comunque. continua.
cledoux,

124

Un'altra soluzione è questa: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

Aggiungi semplicemente un'istruzione OR dopo il tuo comando:

rm -rf my/dir || true

In questo modo, quando l'istruzione n. 1 non riesce (genera un errore), eseguire l'istruzione n. 2, che è semplicemente true.


4
Stampa l'errore e continua l'esecuzione, che era desiderata per il mio caso.
worldsayshi,

9
O solo rm -rf my/dir ||:per essere ancora più conciso ( :è l'abbreviazione di true)
Godsmith,

La soluzione migliore secondo me. È facilmente visibile cosa sta succedendo e perché il codice del risultato viene ignorato. Mi piace!
Mavamaarten,

76

Sono in ritardo alla festa, ma lo uso sempre. In un makefile, aggiungi -all'inizio di una riga per ignorare il valore di ritorno di quella riga. Così:

-rm lexer.ml interpparse.ml interpparse.mli

9
Questo continuerà comunque a stampare errori sulla console, che ti allena a ignorare gli errori nell'output di creazione, che probabilmente non è quello che desideri. rm -rf è un'opzione migliore secondo me.
Godsmith,

@Godsmith Preferirei ignorare un errore piuttosto che forzare l'eliminazione ricorsiva. Questo potrebbe essere molto cattivo. E +1 per la sintassi specifica del makefile
Daishi,

Se rm -rf potrebbe essere "cattivo", significa che stai usando make al di fuori di una directory sotto il controllo della versione. Perché?
Godsmith

Dai un link alla documentazione, per favore. È possibile trovare la descrizione di questa funzione.
George Sovetov,


14

Se non si desidera utilizzare l'opzione -f, un'alternativa è:

rm filethatdoesntexist 2> /dev/null 

Ciò eviterà che gli errori vengano stampati.


9
Sfortunatamente questo fornirà comunque un codice di uscita dell'errore.
Shaun McDonald,

8

Se trovi un modo per globare i nomi dei file, rmnon ti lamenti se non riesce a trovare una corrispondenza. Quindi qualcosa del genere lexer.m* interpparse.*, ecc. Dovrebbe funzionare per te (fai attenzione a non cancellare troppo, ovviamente). Inoltre, -fè un modo perfettamente ragionevole di andare, purché non si speri che i permessi dei file ti salveranno dall'eliminazione di un file che non volevi - se non vuoi eliminarlo, non metterlo nella lista.


Il globbing sarebbe fuori discussione in quanto esiste un file lexer.mll che non voglio eliminare. Grazie per aver mostrato perché -f è ragionevole. Suppongo che tendo ad essere eccessivamente attento dopo una troppa guida sbagliata sudo rm -rf.
Jason Baker,

Nemmeno un più restrittivo lexer.m?...? Ciò catturerebbe lexer.mle lexer.mz, ma non lexer.mllo lexer.mla.
JMD,

1
@JMD: Suppongo che dipenda dalla tua shell e dal supporto di pattern-matching che offre per il globbing.
Nick Bastin,

6

L'opzione -f significa che non ti verrà richiesto se qualcosa non è come previsto. Ciò non significa che le autorizzazioni non vengano prese in considerazione.

Se non disponi di privilegi sufficienti per rimuovere un file, non verrà rimosso.

MA , se hai abbastanza privilegi per cambiare i privilegi, il tuo file verrà rimosso. Questo è il caso in cui sei il proprietario di un file con autorizzazioni di sola lettura per il proprietario (-r --------). Come proprietario, puoi chmod u+w, quindi rimuoverlo: rm -frimuoverà quel file.


5

Forse potrebbe aiutare una linea simile a:

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

So che questo non è molto intelligente, ma fa il lavoro.


3

Un'alternativa:

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

Troppo male I Makefile non possono condividere le definizioni delle funzioni della shell su più righe.


Hai provato a usare \ (barra rovesciata) alla fine di una riga per farla continuare il prossimo?
circa

@some: Sì, possono essere distribuiti su più righe, ma per condividerle tra ricette devi inserire la definizione in una variabile make.
reinierpost,

3

Ecco cosa uso negli script di shell. Nasconde il messaggio di errore e il codice di errore.

rm doesnotexist 2> /dev/null || echo > /dev/null

che ne dicirm doesnotexist 2&> /dev/null
user8162

1

puoi toccare i file prima di inviarli. che li creerebbe se non esistessero :-)

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

1

rm -rf ppp>/dev/null 2>&1 ti scrivo più nuovo ricevi messaggio di errore Il problema si verifica, se l'errore non viene generato in STDERR 2 ma STDOUT 1 ... Si verifica quando il comando genera non errore ma avviso. Devi impostare il filtro e rimuovere questo messaggio. Ma questo caso è ordinario.


1

prova per vedere se il file esiste prima, se lo fa, quindi passalo a rm. Quindi gli errori di rm saranno significativi. -f o ignorare il messaggio di errore è in genere più comprensivo di quello che una persona vuole. -f potrebbe fare cose che non vuoi che siano fatte.

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

aggiungi più clausole di test se ci sono più file di cui vuoi essere sicuro.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.