eliminar archivos más antiguos


9

Estoy tratando de eliminar archivos antiguos del directorio y dejar solo 3 archivos más nuevos.

cd /home/user1/test

while [ `ls -lAR | grep ^- | wc -l` < 3 ] ; do

    rm `ls -t1 /home/user/test | tail -1`
    echo " - - - "

done

algo está mal con la declaración condicional.

Respuestas:


9

Si desea recorrer los archivos, nunca usels *. tl; dr Hay muchas situaciones en las que terminaría borrando el archivo incorrecto, o incluso todos los archivos.

Dicho esto, desafortunadamente esto es algo complicado de hacer bien en Bash. Hay una respuesta que funciona en una pregunta duplicada incluso más antiguafind_date_sorted que puedes usar con pequeñas modificaciones:

counter=0
while IFS= read -r -d '' -u 9
do
    let ++counter
    if [[ counter -gt 3 ]]
    then
        path="${REPLY#* }" # Remove the modification time
        echo -e "$path" # Test
        # rm -v -- "$path" # Uncomment when you're sure it works
    fi
done 9< <(find . -mindepth 1 -type f -printf '%TY-%Tm-%TdT%TH:%TM:%TS %p\0' | sort -rz) # Find and sort by date, newest first

* No se ofendan, chicos ls. Pero realmente no es seguro.

Editar: Nuevofind_date_sorted con pruebas unitarias.


Secundo la parte sobre no analizar ls. Además, el guión es ordenado, pero creo que se podría hacer de una sola vez, déjame comprobar ...
— rahmu 05 de

Bueno, siempre puedes compactar el código Bash en una sola línea, pero el problema es si será legible :)
— l0b0

2
Si puedo robar sin piedad una idea de @ Peter.O, prueba ((++counter>3))como prueba. Es muy sucinto. En cuanto a los oneliners: si la brevedad es una preocupación, envuelva el código en una función, entonces no se preocupe por eso.
— Sorpigal

@Sorpigal Neat shortcut
— l0b0

5

Para eliminar todos los archivos, excepto los 3 más nuevos, utilizando un zsh glob, puede usar Om(O mayúscula) para ordenar los archivos del más antiguo al más nuevo y un subíndice para obtener los archivos que desee.

rm ./*(Om[1,-4])
#    | ||||  ` stop at the 4th to the last file (leaving out the 3 newest)
#    | |||` start with first file (oldest in this case)
#    | ||` subscript to pick one or a range of files
#    | |` look at modified time
#    | ` sort in descending order
#    ` start by looking at all files

Otros ejemplos:

# delete oldest file (both do the same thing)
rm ./*(Om[1])
rm ./*(om[-1])

# delete oldest two files
rm ./*(Om[1,2])

# delete everything but the oldest file
rm ./*(om[1,-2])

5

Con mucho, el método más fácil es usar zsh y sus calificadores globales : Ompara ordenar disminuyendo la edad (es decir, la más antigua primero) y [1,3]retener solo las tres primeras coincidencias.

rm ./*(Om[1,3])

Vea también ¿Cómo filtro un globo en zsh para más ejemplos?

Y preste atención al consejo de l0b0 : su código se romperá horriblemente si tiene nombres de archivo que contienen caracteres especiales de shell.


Woa woa sostenga el tren, ¿es realmente una solución completa en 1 línea?
— MetaGuru

2
@ Ryan Eso es zsh para ti.
— Gilles 'SO- deja de ser malvado'

1

Puede usar la siguiente función para obtener el archivo más nuevo en un directorio:

newest_in() 
{ 
    local newest=$1

    for f;do [[ $f -nt $newest ]] && newest="$f"; done;

    printf '%s\n' "$newest"
}

Dele un conjunto diferente de archivos al extraer el archivo más nuevo después de cada iteración.

Consejo: Si mantiene el conjunto inicial de archivos en una matriz llamada "$ {files [@]}", guarde el índice del archivo más nuevo encontrado y unset 'files[index]'antes de la siguiente iteración.

Uso: newest_in [set of files/directories]

Salida de muestra:

[rany$] newest_in ./*
foo.txt
[rany$]

-1

Primero, la -Ropción es para la recursividad, que probablemente no sea lo que desea, que también buscará en todos los subdirectorios. Segundo, el <operador (cuando no se ve como redirección) es para la comparación de cadenas. Probablemente quieras -lt. Tratar:

while [ `ls -1A | grep ^- | wc -l` -lt 3 ]

Pero usaría encontrar aquí:

while [ `find . -maxdepth 1 -type f -print | wc -l` -lt 3 ]

Ambos fallarán si uno o más de los nombres de archivo contienen un '$ \ n'.
— Rany Albeg Wein

-1

Sé que es un pecado analizar ls, pero ¿qué pasa con esto?

find . -type f -maxdepth 1 | xargs ls -ltr | sed '1,3d' | awk '{print $9}' | xargs rm

Una prueba rápida con 5 archivos vacíos:

$ >1
$ >2
$ >3
$ >4
$ >5
$ find . -type f -maxdepth 1 | xargs ls -lt | sed '1,3d' | awk '{print $9}' | xargs rm
$ ls -1
3
4
5

Éste fallará por dos razones: analizar la lssalida y usar findy xargsjuntos de manera incorrecta. Si se combinan findy xargste recomiendo que el uso finds -print0y, en consecuencia xargss -Oopciones. Lea sobre Uso de Buscar para obtener más información sobre el tema. También es posible que desee echar un vistazo y leer sobre por qué Analizar ls es muy malo.
— Rany Albeg Wein

-2

Este one-liner lo hace todo lo que pienso:

ls -t1 /home/user/test | tail -n +4 | xargs -I{} rm -- "{}"

ls es una herramienta para mirar interactivamente la información del archivo. Su salida está formateada para humanos y causará errores en los scripts. Usa globos o encuentra en su lugar. Comprenda por qué: mywiki.wooledge.org/ParsingLs
— Rany Albeg Wein

-2

Aquí hay una solución:

rm /appserver/webapplogs/$(ls -t1 /appserver/webapplogs/|tail -1)

1
@bakbak ls es una herramienta para mirar interactivamente la información del archivo. Su salida está formateada para humanos y causará errores en los scripts. Mira aquí para entender por qué . Hablando específicamente sobre su respuesta: esta se romperá si uno o más de los archivos contienen un carácter $ '\ n'. Además, la sustitución de comandos (es decir, $ (...)) carece de comillas dobles, lo que plantea otro tema importante: la división de palabras .
— Rany Albeg Wein
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.