Disons que j'ai un répertoire ḟoo/qui contient beaucoup de fichiers dans une sorte de structure de répertoires. Je dois en garder certains, mais pas tout.
Existe-t-il un moyen (en place) de les supprimer tous sauf (disons) les 500 plus récents?
Disons que j'ai un répertoire ḟoo/qui contient beaucoup de fichiers dans une sorte de structure de répertoires. Je dois en garder certains, mais pas tout.
Existe-t-il un moyen (en place) de les supprimer tous sauf (disons) les 500 plus récents?
Réponses:
Je fais cette tâche régulièrement et j'utilise des variantes des éléments suivants. Il s'agit d'un pipeline combinant divers outils simples: recherchez tous les fichiers, ajoutez l'heure de modification des fichiers, triez, supprimez l'heure de modification des fichiers, affichez toutes les lignes sauf les 500 premières et supprimez-les:
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
Quelques commentaires:
Si vous utilisez "bash", vous devez utiliser "read -r file", pas seulement "read file".
L'utilisation de "perl" pour supprimer les fichiers est plus rapide (et gère également les caractères "bizarres" dans les noms de fichiers mieux que la boucle while, sauf si vous utilisez "read -r file"):
... | tail -n +501 | perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"'
Certaines versions de «tail» ne prennent pas en charge l'option «-n», vous devez donc utiliser «tail +501». Une façon portable de sauter les 500 premières lignes est
... | perl -wnle 'print if $. > 500' | ...
Cela ne fonctionnera pas si vos noms de fichiers contiennent des retours à la ligne.
Il ne nécessite pas de recherche GNU.
La combinaison de ce qui précède vous donne:
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"'
C'est ainsi que je le ferais en Python 3. qui devrait également fonctionner pour d'autres systèmes d'exploitation. Après avoir testé cela, assurez-vous de décommenter la ligne qui supprime réellement les fichiers.
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)
Je ne connais pas les "500 plus récents", mais avec find, vous pouvez supprimer des éléments vieux de X minutes / jours. Exemple pour fichier et plus de 2 jours:
find foo/ -mtime +2 -a -type f -exec rm -fv \{\} \;
Testez d'abord avec:
find foo/ -mtime +2 -a -type f -exec ls -al \{\} \;
Faites attention aux barres obliques inverses et à l'espace avant "\;". Consultez la page de manuel find pour plus d'informations.
pourquoi ne pas utiliser ce code plus simple:
$ ls -t1 foo/| xargs -d '\n' rm --
rm -fcependant.