Solución sin problemas con "ls" (archivos con nombres extraños)
Esta es una combinación de la respuesta de ceving y anubhava. Ambas soluciones no funcionan para mí. Como estaba buscando un script que debería ejecutarse todos los días para realizar copias de seguridad de archivos en un archivo comprimido, quería evitar problemas con ls
(Alguien podría haber guardado algún archivo con un nombre divertido en mi carpeta de respaldo). Así que modifiqué las soluciones mencionadas para adaptarlas a mis necesidades.
Mi solución elimina todos los archivos, excepto los tres archivos más nuevos.
find . -type f -printf '%[email protected]\t%p\n' |
sort -t $'\t' -g |
head -n -3 |
cut -d $'\t' -f 2- |
xargs rm
Alguna explicación:
find
enumera todos los archivos (no directorios) en la carpeta actual. Se imprimen con marcas de tiempo.
sort
ordena las líneas según la marca de tiempo (la más antigua en la parte superior).
head
imprime las líneas superiores, hasta las últimas 3 líneas.
cut
elimina las marcas de tiempo.
xargs
ejecuta rm
para cada archivo seleccionado.
Para que verifiques mi solución:
(
touch -d "6 days ago" test_6_days_old
touch -d "7 days ago" test_7_days_old
touch -d "8 days ago" test_8_days_old
touch -d "9 days ago" test_9_days_old
touch -d "10 days ago" test_10_days_old
)
Esto crea 5 archivos con diferentes marcas de tiempo en la carpeta actual. Ejecute este script primero y luego el código para eliminar archivos antiguos.
Esto listará todos los archivos excepto los tres más nuevos:
ls -t | tail -n +4
Esto eliminará esos archivos:
ls -t | tail -n +4 | xargs rm --
Esto también mostrará una lista de archivos de puntos:
ls -At | tail -n +4
y eliminar con dotfiles:
ls -At | tail -n +4 | xargs rm --
Pero cuidado:analizando ls
puede ser peligroso cuando los nombres de archivo contienen caracteres divertidos como líneas nuevas o espacios. Si está seguro de que sus nombres de archivo no contienen caracteres divertidos, analice ls
es bastante seguro, más aún si es un script de una sola vez.
Si está desarrollando una secuencia de comandos para uso repetido, lo más seguro es que no analice la salida de ls
y use los métodos descritos aquí:http://mywiki.wooledge.org/ParsingLs
ls -t | tail -n +4 | xargs -I {} rm {}
Si quieres una línea 1
Lo siguiente parece un poco complicado, pero es muy cauteloso para ser correcto, incluso con nombres de archivo inusuales o intencionalmente maliciosos. Desafortunadamente, requiere herramientas GNU:
count=0
while IFS= read -r -d ' ' && IFS= read -r -d '' filename; do
(( ++count > 3 )) && printf '%s\0' "$filename"
done < <(find . -maxdepth 1 -type f -printf '%[email protected] %P\0' | sort -g -z) \
| xargs -0 rm -f --
Explicando cómo funciona esto:
- Buscar emite
<mtime> <filename><NUL>
para cada archivo en el directorio actual. sort -g -z
realiza una ordenación numérica general (coma flotante, a diferencia de enteros) basada en la primera columna (veces) con las líneas separadas por NUL.- El primer
read
en elwhile
loop elimina el mtime (ya no es necesario después desort
está hecho). - El segundo
read
en elwhile
loop lee el nombre del archivo (ejecutándose hasta el NUL). - El ciclo incrementa y luego verifica un contador; si el estado del contador indica que hemos superado el salto inicial, imprimimos el nombre del archivo, delimitado por un NUL.
xargs -0
luego agrega ese nombre de archivo a la lista argv que está recopilando para invocarrm
con.