66 votes

Comment supprimer tous les fichiers sauf les 10 plus récents sous Linux ?

J'essaie de garder un répertoire plein de fichiers journaux gérable. Chaque nuit, je veux supprimer tous les fichiers sauf les 10 plus récents. Comment puis-je faire cela en une seule commande ?

1voto

Hauke Laging Points 275

En Bash, vous pouvez essayer :

ls -1t | (i=0; while read f; do
  if [ $i -lt 10 ]; then
    ((i++))
    continue
  else
    rm -f "$f"
  fi
done)

Cela saute les 10 plus récents et supprime le reste. logrotate peut être meilleur, je veux juste corriger les mauvaises réponses liées à Shell.

1voto

Matt Powell Points 4166

De aquí :

#! /bin/sh
# keepnewest
#
# Simple directory trimming tool to handle housekeeping
# Scans a directory and deletes all but the N newest files
#
# Usage: cleanup <dir> <number of files to keep>
#
# v 1.0 Piers Goodhew 1/mar/2007. No rights retained.

if [ $# -ne 2 ]; then
  echo 1>&2 "Usage: $0 <dir> <number of files to keep>"
  exit 1
fi

cd $1
files_in_dir=`ls | wc -l`
files_to_delete=`expr $files_in_dir - $2`
if [ $files_to_delete -gt 0 ]; then
  ls -t | tail -n $files_to_delete | xargs rm
  if [ $? -ne 0 ]; then
    echo "An error ocurred deleting the files"
    exit 1
  else
    echo "$files_to_delete file(s) deleted."
  fi
else
  echo "nothing to delete!"
fi

1voto

Flo Woo Points 131

Je ne suis pas sûr que cela puisse aider qui que ce soit, mais pour éviter les problèmes potentiels avec les caractères bancals, j'ai juste utilisé ls pour effectuer le tri mais ensuite utiliser les fichiers inode pour la suppression.

Pour le répertoire actuel, cela conserve les 10 fichiers les plus récents en fonction de l'heure de modification.

ls -1tri | awk '{print $1}' | head -n -10 | xargs -n1 -t -Iinode find . -inum inode -exec rm -i {} \;

1voto

h0tw1r3 Points 1676

Je suis d'accord pour dire que l'analyse de ls est diabolique !

Assurez-vous que seuls les 5 derniers fichiers sont conservés dans le dossier /srv/backups chemin.

find /srv/backups -maxdepth 1 -type f -printf '%Ts\t%P\n' \
    | sort -rn \
    | tail -n +6 \
    | cut -f2- \
    | xargs -r r

0voto

Pila Points 1

J'avais besoin d'une solution élégante pour le busybox (routeur), toutes les solutions xargs ou array étaient inutiles pour moi - aucune commande de ce type n'est disponible ici. find et mtime n'est pas la bonne réponse car nous parlons de 10 éléments et pas nécessairement de 10 jours. La réponse d'Espo était la plus courte et la plus propre, mais probablement la plus inversale.

Les erreurs avec des espaces et lorsqu'aucun fichier ne doit être supprimé sont toutes deux simplement résolues de la manière standard :

rm "$(ls -td *.tar | awk 'NR>7')" 2>&-

Version un peu plus éducative : On peut tout faire si on utilise l'awk différemment. Normalement, j'utilise cette méthode pour passer (retourner) des variables de l'awk vers le sh. Comme nous lisons tout le temps que ce n'est pas possible, je ne suis pas d'accord : voici la méthode.

Exemple pour les fichiers .tar sans problème concernant les espaces dans le nom du fichier. Pour tester, remplacez "rm" par "ls".

eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}')

Explication :

ls -td *.tar liste tous les fichiers .tar triés par heure. Pour s'appliquer à tous les fichiers du dossier actuel, supprimez la partie "d *.tar".

awk 'NR>7... saute les 7 premières lignes

print "rm \"" $0 "\"" construit une ligne : rm "nom du fichier".

eval l'exécute

Puisque nous utilisons rm Je n'utiliserais pas la commande ci-dessus dans un script ! L'utilisation la plus sage est :

(cd /FolderToDeleteWithin && eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}'))

Dans le cas de l'utilisation de ls -t ne fera pas de mal sur des exemples aussi stupides que ceux-là : touch 'foo " bar' y touch 'hello * world' . Non pas que nous créions des fichiers avec de tels noms dans la vie réelle !

Sidenote. Si nous voulions passer une variable au sh de cette manière, nous modifierions simplement le print :

print "VarName="$1

pour définir la variable VarName à la valeur de $1 . Plusieurs variables peuvent être créées en une seule fois. Ce site VarName devient une variable sh normale et peut être utilisée normalement dans un script ou script par la suite. Donc, pour créer des variables avec awk et les rendre à la script :

eval $(ls -td *.tar | awk 'NR>7 { print "VarName="$1 }'); echo "$VarName"

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X