Escribí un script que elimina todos excepto los dos últimos archivos en una carpeta:
#!/bin/bash
ls -1 --quoting-style=shell-always /path/to/some/folder \
| head -n -2 \
| xargs printf -- "'/path/to/some/folder/%s'\n" \
| xargs sudo rm -rf
Este script se ejecutará como un trabajo cron todos los días.
El razonamiento es como sigue:
Obtenga una lista de todos los archivos usando
ls -1
(para que obtenga un archivo por línea);Elimine los dos últimos de la lista usando
head -n -2
;Dado que
ls
imprime rutas relativas, use el elementoxargs printf
para anteponer la ruta de la carpeta y convertirla en una ruta absoluta;Envíalos a
sudo rm -rf
usarxargs
.
Todos tienen acceso a esta carpeta, por lo que cualquiera puede crear y eliminar cualquier archivo en esta carpeta.
El problema es: sudo rm -rf
da miedo. xargs sudo rm -rf
Es increíblemente aterrador.
Quiero asegurarme de que nadie pueda dañar otras carpetas / sistemas creando archivos inteligentes que se eliminen (ya sea accidentalmente o a propósito). No sé, algo inteligente como:
file with / spaces.txt
lo que podría resultar en un súper miedo sudo rm -rf /
.
EDITAR: Mi error, los nombres de archivo no pueden contener /
, por lo que este problema específico no sucedería, pero la pregunta sobre si existen otros riesgos o no.
Es por eso que estoy usando --quoting-style=shell-always
, esto debería evitar cualquier truco con archivos con espacios. Pero ahora me pregunto si alguien podría ser más inteligente con espacios y comillas en el nombre de archivo, tal vez.
¿Es seguro mi script?
Nota: Lo necesito sudo
porque estoy accediendo a la carpeta de forma remota (desde una unidad de red asignada usando mount
), y no pude hacer que funcione sin sudo.
printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm
?/
Puedo crear un archivo con el personaje en el nombre? Estoy tratando de lograr esto aquíls
salida, este ya es un comando mal escrito, incluso con comillas.ls
creo que también usa la configuración regional para ordenar el orden, así que no veo cuál es el propósito dehead
eliminar los últimos 2 (a menos que estés tratando de deshacerte.
y de..
qué iirc no están permitidos como argumentos derm
todos modos. Solo usafind /path/to/folder -type f delete
. Y nosudo
si se ejecuta desde cron - cron ya está en el nivel raízRespuestas:
En Linux, cualquier carácter es un nombre de archivo válido que constituye un carácter, excepto:
\0
(ASCII NUL): como se usa para la terminación de cadena en C/
(barra inclinada): como se usa para la separación del caminoEntonces, su enfoque definitivamente no funcionará en muchos casos, como puede imaginar, por ejemplo, ¿maneja una nueva línea (
\n
) en el nombre del archivo? ( Sugerencia: no ).Pocas notas:
ls
; use herramientas dedicadas (hay al menos una para la mayoría de los casos de uso)xargs
, vea si puede salirse con la suyafind ... -exec
; en la mayoría de los casos, estarás bienfind
soloCreo que esto te pondrá en marcha por ahora. steeldriver ya proporcionó la idea separada por NUL en el comentario (
printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm
), use esto como punto de partida.fuente
find
también, gracias por la sugerencia.ls
enfoque de análisis podría fallar, por ejemplo, ¿tuvo en cuenta una nueva línea en el nombre del archivo?head -z
? Suena ridículo, pero no tengoman
niinfo
en mi contenedor CoreOS Linux ... Tampoco pude encontrar en Internet. Obtengohead: invalid option 'z'
head
(viene con GNUcoreutils
). Aquí está la versión en línea: manpages.ubuntu.com/manpages/xenial/man1/head.1.htmlxargs
admite algunas citas: con comillas simples, comillas dobles o barra diagonal inversa que le permite aceptar argumentos arbitrarios¹, pero con una sintaxis que es diferente de la sintaxis de comillas tipo Bourne.La implementación de GNU
ls
como se encuentra en Ubuntu no tiene ningún modo de cotización que sea compatible con elxargs
formato de entrada.Su
ls --quoting-style=shell-always
es compatible con ksh93, golpe y conchas zsh citando sintaxis, pero sólo cuando la salida dells
es interpretado por el shell en el mismo lugar comols
era cuando salida de él. Además, se deben evitar algunos entornos locales, como los que usan BIG5, BIG5-HKSCS, GBK o GB18030.Entonces, con esos proyectiles, puedes hacer:
Pero eso tiene poca ventaja sobre:
El único caso en el que se vuelve útil es cuando desea utilizar la
-t
opción dels
ordenar los archivos por mtime / atime / ctime o-S
/-V
. Pero incluso entonces, también podrías usarzsh
:por ejemplo, para ordenar los archivos por mtime (use
oL
for-S
yn
for-V
).Para eliminar todos menos los dos archivos regulares modificados más recientemente:
¹ todavía hay algunas limitaciones de longitud (por
execve()
y en algunasxargs
implementaciones no GNU arbitrarias mucho más bajas), y algunasxargs
implementaciones no GNU ahogarán la entrada que contiene secuencias de bytes que no forman caracteres válidos.fuente