¿Cómo hago para que rm no dé un error si no existe un archivo?

329

Estoy escribiendo un archivo MAKE que limpiará algunos archivos inútiles al final de la compilación. Si ya se ha creado un objetivo, por supuesto se saltará ese objetivo y es posible que el archivo inútil no esté allí. Entonces si hago esto:

rm lexer.ml interpparse.ml interpparse.mli

Es posible que obtenga errores porque uno de los archivos no existe. ¿Hay alguna forma de decir rmque ignore estos archivos?

Al leer la página del manual, veo la siguiente opción:

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

Eso suena casi como lo que quiero, pero no estoy muy seguro de la parte de permisos. ¿Hay alguna forma de hacer esto?

Jason Baker
fuente
¿Probaste un poco rmen una caja de arena? Parece que -fhace exactamente lo que quieres, sin importar el tipo de problema.
JMD
Si los permisos no lo permiten, rm con la -fopción aún intentará eliminarlo. Fallará. No te dirá que falló. Útil si el nombre de archivo es una variable o un globo.
LawrenceC
solo para completar: hay rm --interactive=nevercuales actúan como, rm -fexcepto que devuelve un estado de salida de error. ver aquí para más detalles: unix.stackexchange.com/questions/72864/…
lesmana

Respuestas:

283

La -fopción es definitivamente lo que quieres usar.

La confirmación sobre los permisos de archivo a los que se refiere es esta:

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

Por rmlo tanto, te advertirá si intentas eliminar un archivo en el que no tienes permisos de escritura. Esto está permitido si tiene permisos de escritura en el directorio, pero es un poco extraño, por lo que rmnormalmente le advierte al respecto.

Dave Webb
fuente
1
La mayoría, pero no todos los sistemas preguntarán (creo). Algunos requieren -i.
DaveParillo
1
Si desea el mensaje de error, pero no el código de salida de error, vea la respuesta de Giel Berkers . Lo uso set -een todos mis scripts de bash para que el script salga después de que cualquier comando dé un error. A menudo quiero un script que me diga si se rmprodujo un error, pero continúo de todos modos. continúa
cledoux
124

Otra solución es esta: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

Simplemente agregue una instrucción OR después de su comando:

rm -rf my/dir || true

De esta manera, cuando la declaración n. ° 1 falla (arroja un error), ejecute la declaración n. ° 2, que es simplemente true.

Giel Berkers
fuente
44
Imprime el error y continúa la ejecución, lo que era deseado para mi caso.
worldsayshi
99
O simplemente rm -rf my/dir ||:para ser aún más conciso ( :es la abreviatura de true)
Godsmith
La mejor solución en mi opinión. Es fácilmente visible lo que está sucediendo y por qué se ignora el código de resultado. ¡Me gusta!
Mavamaarten
76

Llego tarde a la fiesta, pero uso esto todo el tiempo. En un archivo MAKE, agregue -al principio de una línea para ignorar el valor de retorno de esa línea. Al igual que:

-rm lexer.ml interpparse.ml interpparse.mli
Robert Li
fuente
99
Sin embargo, esto todavía imprimirá un error en la consola, lo que lo capacitará para ignorar los errores en la salida de creación, que probablemente no sea lo que desea. rm -rf es una mejor opción en mi opinión.
Godsmith
@ Godsmith Prefiero ignorar un error que forzar la eliminación recursiva. Esto podría ser muy travieso. Y +1 para la sintaxis específica del archivo MAKE
Daishi
Si rm -rf podría ser "travieso", significa que está utilizando make fuera de un directorio bajo control de versiones. ¿Por qué?
Godsmith
Dé un enlace a la documentación, por favor. Podría encontrar una descripción de esta característica.
George Sovetov
14

Si no desea utilizar la opción -f, una alternativa es:

rm filethatdoesntexist 2> /dev/null 

Esto solo evitará que se impriman errores.

usuario135299
fuente
99
Lamentablemente, esto todavía dará un código de error de salida.
Shaun McDonald
8

Si encuentra alguna forma de glob los nombres de archivo, rmno se quejará si no puede encontrar una coincidencia. Entonces, algo como lexer.m* interpparse.*, etc., debería funcionar para usted (tenga cuidado de no eliminar demasiado, por supuesto). Además, -fes un camino perfectamente razonable, siempre y cuando no esperes que los permisos de archivo te salven de eliminar un archivo que no querías; si no quieres eliminarlo, no lo pongas en la lista.

Nick Bastin
fuente
El globbing estaría fuera de discusión ya que hay un archivo lexer.mll que no quiero eliminar. Gracias por mostrar por qué -f es razonable. Supongo que tiendo a ser demasiado cuidadoso después de demasiados equivocados sudo rm -rf.
Jason Baker
Ni siquiera un más restrictivo lexer.m?...? Eso atraparía lexer.mly lexer.mz, pero no lexer.mllo lexer.mla.
JMD
1
@JMD: supongo que depende de su shell y de la compatibilidad de coincidencia de patrones que ofrece para globbing.
Nick Bastin el
6

La opción -f significa que no se le preguntará si algo no es como se esperaba. No significa que los permisos no se tengan en cuenta.

Si no tiene suficientes privilegios para eliminar un archivo, no se eliminará.

PERO , si tiene suficientes privilegios para cambiar privilegios, su archivo será eliminado. Este es el caso cuando es el propietario de un archivo con permisos de solo lectura para el propietario (-r --------). Como propietario, puede chmod u+w, luego eliminarlo: rm -feliminará ese archivo.

Mouviciel
fuente
5

Tal vez podría ayudar una línea similar con:

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

Sé que esto no es muy inteligente, pero hace el trabajo.

Bogdan
fuente
3

Una alternativa:

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

Lástima que los Makefiles no puedan compartir definiciones de funciones de shell entre líneas.

reinierpost
fuente
¿Has intentado usar \ (barra diagonal inversa) al final de una fila para permitir que continúe en la siguiente?
algunos
@some: Sí, pueden extenderse a través de varias líneas, pero para compartirlas entre recetas debe colocar la definición en una variable de creación.
reinierpost
3

Esto es lo que uso en los scripts de shell. Oculta el mensaje de error y el código de error.

rm doesnotexist 2> /dev/null || echo > /dev/null
teh_senaus
fuente
¿qué talrm doesnotexist 2&> /dev/null
user8162
1

Puede tocar los archivos antes de ejecutarlos. eso los crearía si no existen :-)

touch lexer.ml interpparse.ml interpparse.mli
rm lexer.ml interpparse.ml interpparse.mli
Pico común
fuente
1

escriba rm -rf ppp>/dev/null 2>&1 su mensaje de error más reciente. Se produce un problema, si el error no se genera en STDERR 2 sino en STDOUT 1 ... Se produce cuando el comando genera no error sino advertencia. Debe configurar el filtro y eliminar este mensaje. Pero este caso es ordinario.

Anatoly
fuente
1

prueba para ver si el archivo existe primero, si es así, luego pásalo a rm. Entonces los errores de rm serán significativos. -f o ignorar el mensaje de error suele ser más abarcador de lo que una persona quiere. -f podría hacer cosas que no quieres que se hagan.

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

agregue más cláusulas de prueba si hay más archivos que desea asegurarse de que existan.


fuente