Eliminar todo excepto los archivos más nuevos

8

Digamos que tengo un directorio ḟoo/que contiene muchos archivos en algún tipo de estructura de directorios. Necesito mantener algunos de ellos, pero no todos.

¿Hay alguna manera de (en su lugar) eliminarlos todos excepto (digamos) 500 más nuevos?

Dalibor Karlović
fuente

Respuestas:

11

Hago esta tarea regularmente y uso variantes de lo siguiente. Es una tubería que combina varias herramientas simples: encontrar todos los archivos, anteponer el tiempo de modificación del archivo, ordenar, eliminar el tiempo de modificación del archivo, mostrar todas las líneas excepto las 500 primero y eliminarlas:

find foo/ -type f | perl -wple 'printf "%12u ", (stat)[9]' | \
    sort -r | cut -c14- | tail -n +501 | \
    while read file; do rm -f -- "$file"; done

Algunos comentarios

  • Si está usando "bash", debe usar "read -r file", no solo "read file".

  • Usar "perl" para eliminar los archivos es más rápido (y también maneja los caracteres "extraños" en los nombres de archivo mejor que el ciclo while, a menos que esté usando "leer -r archivo"):

    ... | tail -n +501 | perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"'
    
  • Algunas versiones de "tail" no admiten la opción "-n", por lo que debe usar "tail +501". Una forma portátil de saltear las 500 primeras líneas es

     ... | perl -wnle 'print if $. > 500' | ...
    
  • No funcionará si sus nombres de archivo contienen nuevas líneas.

  • No requiere encontrar GNU.

Combinar lo anterior te da:

find foo/ -type f | perl -wple 'printf "%12u ", (stat)[9]' | \
    sort -r | cut -c14- | perl -wnle 'print if $. > 500' | \
    perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"'
Peter John Acklam
fuente
Sin embargo, sería cuidadoso rm -f.
un CVn
¡Funciona de maravilla! Esto debería estar disponible como un alias con $ path y $ count params. ¡Muchas gracias!
Dalibor Karlović
4

Así es como lo haría en Python 3. que también debería funcionar para otros sistemas operativos. Después de probar esto, asegúrese de descomentar la línea que realmente elimina los archivos.

import os,os.path
from collections import defaultdict

FILES_TO_KEEP = 500
ROOT_PATH = r'/tmp/'

tree = defaultdict(list)

# create a dictionary containing file names with their date as the key
for root, dirs, files in os.walk(ROOT_PATH):
    for name in files:
        fname = os.path.join(root,name)
        fdate = os.path.getmtime( fname )
        tree[fdate].append(fname)

# sort this dictionary by date
# locate where the newer files (that you want to keep) end
count = 0
inorder = sorted(tree.keys(),reverse=True)
for key in inorder:
    count += len(tree[key])
    if count >= FILES_TO_KEEP:
        last_key = key
        break

# now you know where the newer files end, older files begin within the dict
# act accordingly
for key in inorder:
    if key < last_key:
        for f in tree[key]:
            print("remove ", f)
            # uncomment this next line to actually remove files
            #os.remove(f)
    else:
        for f in tree[key]:
            print("keep    ", f)
jftuga
fuente
4

No sé acerca de los "500 más nuevos", pero con find puedes eliminar cosas que tienen más de X minutos / días. Ejemplo para archivo y más de 2 días:

find foo/ -mtime +2 -a -type f -exec rm -fv \{\} \;

Prueba primero con:

find foo/ -mtime +2 -a -type f -exec ls -al \{\} \;

Tenga en cuenta las barras invertidas y el espacio antes de "\;". Consulte la página del manual de búsqueda para obtener más información.

AndreasM
fuente
El "(digamos) 500 más nuevo" es la esencia aquí, así que no veo cómo esto responde a la pregunta original.
Peter John Acklam
Lo siento, no estaba claro para mí.
AndreasM
3

si pudieras mantener archivos x días / horas de antigüedad en lugar del número x más nuevo, podrías hacerlo solo con tmpwatch --ctime 7d

Sirex
fuente
2

Creo que el -mtimey -neweropciones de findcomando son útiles para usted. Puedes ver man findpara más información.

Khaled
fuente
0

por qué no usar este código más simple:

$ ls -t1 foo/| xargs -d '\n' rm --
eppesuig
fuente
1
¿Cómo elimina esto todos los archivos excepto los 500 archivos más recientes? ¿Y cómo maneja esto los subdirectorios? Creo que es posible que hayas entendido mal la publicación original.
Peter John Acklam