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


Estoy escribiendo un archivo MAKE que limpiará algunos archivos inútiles al final de la compilación. Si ya se ha hecho un objetivo, saltará ese objetivo y el archivo inútil puede no estar 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 manera de decirlo rm ignorar estos archivos?

Al leer la página man, 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 como casi lo que quiero, pero no estoy seguro de la parte de permisos. ¿Hay alguna forma de hacer esto?


261


origen


¿Has probado alguna rm en una caja de arena? Parece que -f hace exactamente lo que quiere, independientemente de los globbing. - JMD
Si los permisos no lo permiten, rm lo hará con el -f opción aún intente eliminarlo. Fallará No te dirá que falló. Útil si el nombre de archivo es una variable o un glob. - LawrenceC


Respuestas:


los -f la opción es definitivamente lo que quieres usar.

La confirmación de los permisos de archivos a los que se refiere es la siguiente:

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

Asi que rm le advertirá si intenta eliminar un archivo en el que no tiene permisos de escritura. Esto está permitido si tienes permisos de escritura en el directorio, pero es un poco raro, por eso rm normalmente te lo advierte


221



La mayoría, pero no todos los sistemas preguntarán (creo). Algunos requieren -i. - DaveParillo
Si desea el mensaje de error, pero no el código de salida de error, consulte la respuesta por Giel Berkers. yo suelo set -e en todos mis scripts bash para que el script salga después de que cualquier comando da un error. A menudo quiero un script para decirme si rm dio un error, pero continúe de todos modos. continúa - cledoux


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

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

rm -rf my/dir || true

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


77



Imprime el error y continúa la ejecución, que era deseada para mi caso. - worldsayshi
O solo rm -rf my/dir ||: 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


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

-rm lexer.ml interpparse.ml interpparse.mli

69



Sin embargo, esto todavía imprimirá un error en la consola, lo que lo capacita para ignorar los errores en la salida de make, que probablemente no sea lo que usted 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 "malo", significa que está utilizando make fuera de un directorio bajo control de versión. ¿Por qué? - Godsmith
Proporcione un enlace a la documentación, por favor. Podría encontrar una descripción de esta característica. - George Sovetov
@GeorgeSovetov gnu.org/software/make/manual/make.html#Errors - Robert Li


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

rm filethatdoesntexist 2> /dev/null 

Esto evitará que se impriman errores.


8



Lamentablemente, esto todavía dará un código de salida de error. - Shaun McDonald


Si encuentras alguna forma de glob los nombres de los archivos, rm no se quejará si no puede encontrar una coincidencia. Así que algo así como lexer.m* interpparse.*, etc. debería funcionar para usted (tenga cuidado de no borrar demasiado, por supuesto). También, -f es una forma perfectamente razonable de hacerlo, siempre que no espere que los permisos de archivo le eviten borrar un archivo que no deseaba; si no desea eliminarlo, no lo coloque en el lista.


7



El globbing estaría descartado 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 un exceso de equivocaciones sudo rm -rf . - Jason Baker
Ni siquiera un más restrictivo lexer.m? ...? Eso atraparía lexer.ml y lexer.mz, pero no lexer.mll o lexer.mla. - JMD
@JMD: Supongo que depende de tu caparazón y de la compatibilidad de coincidencia de patrones que ofrece para englobar. - Nick Bastin


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 los privilegios, su archivo será eliminado. Este es el caso cuando usted es el propietario de un archivo con permisos de solo lectura para el propietario (-r --------). Como propietario, puedes chmod u+w, luego quítalo: rm -f eliminará ese archivo.


5





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

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

Sé que esto no es muy inteligente, pero cumple su función.


3





Una alternativa:

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

Es una pena que los Makefiles no puedan compartir definiciones de funciones de shell entre líneas.


2



¿Has intentado utilizar \ (barra invertida) al final de una fila para que continúe en la siguiente? - some
@some: Sí, pueden distribuirse en varias líneas, pero para compartirlas en las recetas, debe poner la definición en una variable make. - reinierpost


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

2





puedes tocar los archivos antes de activarlos. eso los crearía si no existieran :-)

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

0