¿Rm -rf * eliminará todos los archivos / carpetas en el directorio actual?

20

¿ rm -rf *Eliminará todos los archivos / carpetas en el directorio actual? Quiero asegurarme de que el comodín *no se mueva hacia arriba en los directorios superiores y borre todo mi sistema de archivos. :RE

Recuerdo que hace chmod 777 .* -Ra chmodlos archivos ocultos y chmoded todo mi sistema de archivos. Obviamente, estaba en la cuenta raíz.

Olivier Lalonde
fuente
1
Es por eso que haría rm -rf ./*y especificaría explícitamente el directorio actual ... pero Ankur parece decir que no importa de todos modos.
mpen
@ Mark: ¿cuál es la diferencia entre .. y ./ ..? Puede intentar cd ./ .. y ver dónde termina :)
Johan
@Johan: No hay diferencia ... Creo que tiene más sentido en mi cabeza loca: D
mpen
@ Mark: error fácil de hacer :)
Johan

Respuestas:

15

No, si no ajustó mucho su shell, esto no eliminará archivos o directorios que comiencen con a .. Para eliminarlos también, puede enumerarlos explícitamente

rm -rf .file .dir

o usa los patrones de glob correctos (gracias Chris)

rm -rf .[^.]* ..?*

EDITAR El punto aquí es que no puede usar .*para hacer coincidir archivos como .file, porque .*o .*?también coincidirá con ..o .. .[^.]*coincide con archivos como .file, mientras ..?*coincide con archivos como ..foo( *coincide con cero o más caracteres mientras ?coincide exactamente con uno).

Benjamin Bannier
fuente
1
También necesita algo como ..?*capturar entradas que comienzan con ".." (por ejemplo ..foo).
Chris Johnsen el
@Chris: OK, comencé esta locura quisquillosa, tienes razón;)
Benjamin Bannier
no se trata solo de usar los patrones de glob "correctos", sino también de la cantidad de elementos coincidentes. en directorios con una gran cantidad de archivos, es muy probable que el shell no pueda dar 50k archivos a la vez rm. por lo tanto, eliminar el contenido de un directorio con * no es la forma más inteligente, en mi humilde opinión.
akira
Creo que explicar xargsestá un poco más allá del alcance de esta pregunta. Uno podría, por ejemplo, comenzar a pensar en eso cuando el shell se queja de las longitudes de la lista de argumentos.
Benjamin Bannier
1
Creo que no está fuera de alcance porque creo que OP no está seguro de cómo lograr su último problema / solución: eliminar todo el contenido del directorio. OP está haciendo lo general "incorrecto" al tener en mente una solución (una mala) y preguntando por qué esta solución causa problemas. El mejor enfoque sería: "¿Cómo eliminar todos los archivos en un directorio sin eliminar el directorio en sí?" La solución de OP causará problemas debido a la naturaleza misma de cómo funciona el globbing.
akira
12

Si desea eliminar un directorio y todo su contenido, puede chdiringresar al directorio principal y a rm -rfese directorio por nombre, omitiendo toda la pregunta global. Si desea eliminar el contenido pero mantener el directorio, es más fácil eliminar todo y luego volver a crear el directorio.

Es complejo crear un globo que coincida con todas las entradas de directorio posibles. y ..; es fácil encontrar una respuesta simple (por ejemplo, * .??*) que funcionará casi siempre en la práctica. Esto está bien para uso interactivo, ya que es fácil de recordar y las veces que no funciona pueden detectarse con un post-rm ls -a. Para un script, es más fácil eliminar todo y volver a crear el directorio vacío.

mpez0
fuente
1
Eso es lo que sugeriría también: tirar el directorio y listo
akira el
Incluso si no es la respuesta, es una buena idea.
Johan
10

Como creo que esta pregunta es más sobre qué * hace (y no rm), intentemos con otro enfoque.


Si no está seguro de lo que hace el *, puede "probar" primero usando un comando inofensivo como echo. Antes de ejecutar esto, intente adivinar qué mostrarán si los ejecuta en el directorio de inicio.

echo *
echo .*

Pero primero creemos un patio de juegos para que podamos jugar con las estrellas y ver con qué terminamos.

mkdir ~/star_test/
cd ~/star_test/
>.file1
>file2

Ahora en este directorio tenemos esto:

cj@zap:~/star_test$ ls -1a
.
..
.file1
file2

Ahora observe en qué se expande el * usando el comando echo:

cj@zap:~/star_test$ echo *
file2
cj@zap:~/star_test$ echo .*
. .. .file1

Entonces, veamos qué sucede con el comando rm

cj@zap:~/star_test$ rm -rf *
cj@zap:~/star_test$ ls -1a
.
..
.file1

Como puede ver, solo eliminó el archivo2, ya que * solo se expandió a archivo2. Si escribes rm -rf. * Eso sería lo mismo que escribir

rm -rf . .. .file1

Y para ser sincero, eso no parece divertido;)

Espero que esto aclare la parte * de su pregunta.


Actualización: Sin embargo, como señala Ankur Goel, hay algún tipo de protección integrada en rm (algo inusual para los comandos de shell :)

Creemos un nuevo patio de recreo:

cd ~/star_test/
mkdir -p test1/test2/test3
sudo chown root.root test1
cd test1/test2/test3/
>.file1
>file2

Así que ahora tenemos esto de nuevo, pero con test1 propiedad de root como protección si rm comienza a enloquecer.

cj@zap:~/star_test/test1/test2/test3$ ls -a
.  ..  file2  .file1
cj@zap:~/star_test/test1/test2/test3$ echo .*
. .. .file1

Entonces, eliminemos todo:

cj@zap:~/star_test/test1/test2/test3$ rm -rf .*
rm: cannot remove directory `.'
rm: cannot remove directory `..'
cj@zap:~/star_test/test1/test2/test3$ ls -a
.  ..  file2

Y parece que rm no se eliminó. y .. incluso si le dijéramos que lo hiciera !!!

Entonces, después de esta larga respuesta, resulta seguro eliminar todo en un directorio con esto:

rm -rf * .*

Pero usaría esto con cuidado, ya que no estoy seguro de que todas las implementaciones de rm se comporten así.

Johan
fuente
7

Sí. rm -rf solo eliminará archivos y carpetas en el directorio actual, y no ascenderá por el árbol de archivos. rm tampoco seguirá los enlaces simbólicos y eliminará los archivos a los que apuntan, por lo que no puede podar accidentalmente otras partes de su sistema de archivos.

Ankur Goel
fuente
1

Si no desea subir un nivel como dijo mpez0 y rm -rfesta carpeta específica, hay una manera de trabajar en todos los directorios / archivos excepto .y ..en la carpeta actual haciendo:

rm -rf $(ls -A)

Por supuesto, si alguno de los directorios / archivos contiene uno de los caracteres en la IFSvariable especial de shell (por ejemplo, espacio, tabulación, nueva línea), es posible que desee cambiar el IFS primero, ejecutar el comando y luego restaurar el IFS.

tzot
fuente
0

Una forma mucho más fácil de vaciar una carpeta completa, evitando también los problemas de "demasiados argumentos" discutidos en esta respuesta , es simplemente eliminar y volver a crear el directorio en sí. Para asegurarse de que esto funciona correctamente cuando está en un directorio con enlaces simbólicos, use las siguientes líneas:

cd ..
rm -rf $(readlink -f yourdir) #remove the directory, treat the case of a symlink
                        # by using readlink, to recreate the linked-to directory
mkdir $(readlink -f yourdir) # recreate the directory to have it empty
cd yourdir

(Si usa en yourdirlugar de $(readlink -f yourdir)solo reemplazaría el enlace mientras la ubicación original permanezca llena)

Tobias Kienzler
fuente
1
Esto puede romper cosas que dependen del inodo de la carpeta y tirar permisos, atime / mtime / ctime / btime, atributos extendidos y listas de control de acceso.
Daniel Beck
@DanielBeck gracias, buenos puntos. Aunque me pregunto, ¿qué confiaría válidamente en el inodo aparte de los enlaces duros (en directorios, que de todos modos se desaconsejan)? Pero los permisos, etc. es importante. Entonces, en el caso más general, uno probablemente debería usar xargs...
Tobias Kienzler
OS X contiene un mecanismo que puede manejar archivos y carpetas que se mueven y aún conserva la asociación. Lo más visible en el menú Abrir documentos recientes . AFAICT, utiliza inodes para lograr eso internamente. Más información . No me sorprendería si otros sistemas implementaran algo similar, por ejemplo, en API para programas GUI.
Daniel Beck