Bash : supprimer tous les fichiers et sous-répertoires d’un répertoire avec find

L’autre jour, je voulais faire un peu de ménage dans les logs mod_security d’un serveur. Le répertoire d’audit commençait à prendre de l’ampleur, et il fallait supprimer son contenu sans supprimer le répertoire lui-même.

Je pensais m’en sortir avec un simple rm /dossier, mais ce n’est pas la bonne commande. rm ne supprime pas un répertoire non vide sans option récursive, et un rm -rf mal placé peut vite transformer un petit ménage en épisode judiciaire.

La méthode propre consiste à utiliser find avec -mindepth 1 et -delete. On supprime ainsi tout ce qui se trouve dans le répertoire, sans supprimer le répertoire parent.

Vider un répertoire sans supprimer le dossier parent

Pour supprimer tous les fichiers et sous-répertoires contenus dans /home/logs/, sans supprimer /home/logs/ lui-même :

find /home/logs/ -mindepth 1 -deleteCode language: JavaScript (javascript)

L’option -mindepth 1 indique à find de ne pas agir sur le point de départ lui-même. Autrement dit, /home/logs/ est conservé, mais tout son contenu est supprimé.

L’option -delete supprime les fichiers et répertoires trouvés. La documentation GNU findutils précise que -delete supprime les fichiers trouvés et implique -depth, ce qui permet de supprimer les contenus avant les répertoires parents. Voir la documentation GNU findutils sur -delete.

Prévisualiser avant de supprimer

Avant de lancer une suppression, commencez toujours par afficher ce qui sera ciblé :

find /home/logs/ -mindepth 1 -printCode language: PHP (php)

ou simplement :

find /home/logs/ -mindepth 1

Si la liste correspond bien à ce que vous voulez supprimer, ajoutez ensuite -delete :

find /home/logs/ -mindepth 1 -deleteCode language: JavaScript (javascript)

Ce petit test évite les surprises. Et avec les commandes de suppression, les surprises ont rarement un bon sens de l’humour.

Supprimer aussi le répertoire parent

Si vous souhaitez supprimer le contenu et le répertoire parent, retirez -mindepth 1 :

find /home/logs/ -deleteCode language: JavaScript (javascript)

Cette commande supprime /home/logs/ lui-même, en plus de ses fichiers et sous-répertoires.

Dans la plupart des tâches de maintenance, notamment pour les logs, on veut plutôt conserver le dossier parent. Les applications s’attendent souvent à ce que le répertoire existe, avec des permissions précises.

Pourquoi utiliser find plutôt que rm -rf ?

On peut vider un répertoire avec rm -rf, par exemple :

rm -rf /home/logs/*

Mais cette méthode a plusieurs limites :

  • elle ne supprime pas les fichiers cachés avec un simple * ;
  • elle dépend du globbing du shell ;
  • elle peut échouer avec énormément de fichiers à cause de la limite d’arguments ;
  • elle devient dangereuse si la variable ou le chemin est mal construit ;
  • elle est moins flexible pour filtrer par date, type ou nom.

find parcourt le répertoire lui-même et peut filtrer précisément ce qu’il supprime. C’est plus adapté aux gros répertoires, aux logs, aux caches, aux fichiers temporaires et aux suppressions conditionnelles.

Distingo, le livret à 2%

Attention aux fichiers cachés

Avec rm -rf /home/logs/*, les fichiers cachés comme .cache, .htaccess ou .hidden-file ne sont pas ciblés par défaut.

Avec find, ils le sont :

find /home/logs/ -mindepth 1 -deleteCode language: JavaScript (javascript)

Cette commande supprime aussi les fichiers cachés contenus dans le dossier. C’est souvent ce que l’on veut lorsqu’on vide un répertoire, mais cela mérite d’être connu.

Supprimer uniquement les fichiers, pas les dossiers

Si vous voulez supprimer uniquement les fichiers, en conservant l’arborescence des dossiers :

find /home/logs/ -type f -deleteCode language: JavaScript (javascript)

Cette commande supprime tous les fichiers sous /home/logs/, mais laisse les répertoires en place.

Pour prévisualiser :

find /home/logs/ -type f -printCode language: PHP (php)

Supprimer uniquement les répertoires vides

Pour supprimer seulement les répertoires vides :

find /home/logs/ -mindepth 1 -type d -empty -deleteCode language: JavaScript (javascript)

C’est utile après une suppression de fichiers, lorsque vous voulez nettoyer les dossiers devenus inutiles sans toucher aux répertoires qui contiennent encore quelque chose.

Supprimer les fichiers plus anciens qu’un certain âge

Pour un répertoire de logs, il est rarement nécessaire de tout supprimer. On peut cibler uniquement les fichiers anciens.

Supprimer les fichiers de plus de 30 jours :

find /home/logs/ -type f -mtime +30 -deleteCode language: JavaScript (javascript)

Prévisualiser avant suppression :

find /home/logs/ -type f -mtime +30 -printCode language: PHP (php)

-mtime +30 cible les fichiers dont la date de modification remonte à plus de 30 jours. C’est souvent plus propre qu’un grand nettoyage brutal.

Supprimer les fichiers selon leur extension

Pour supprimer uniquement des fichiers .log :

find /home/logs/ -type f -name '*.log' -deleteCode language: JavaScript (javascript)

Pour les fichiers compressés de logs :

find /home/logs/ -type f \( -name '*.gz' -o -name '*.zip' -o -name '*.xz' \) -deleteCode language: JavaScript (javascript)

Prévisualisez toujours la sélection :

find /home/logs/ -type f \( -name '*.gz' -o -name '*.zip' -o -name '*.xz' \) -printCode language: PHP (php)

Nettoyer un répertoire de logs mod_security

Pour nettoyer les logs de mod_security, si vous avez utilisé la même configuration que moi, le répertoire d’audit peut se trouver ici :

/var/asl/data/audit/Code language: JavaScript (javascript)

Prévisualisez d’abord :

sudo find /var/asl/data/audit/ -mindepth 1 -printCode language: PHP (php)

Puis supprimez le contenu :

sudo find /var/asl/data/audit/ -mindepth 1 -deleteCode language: JavaScript (javascript)

Si vous voulez seulement supprimer les vieux fichiers d’audit, par exemple ceux de plus de 14 jours :

sudo find /var/asl/data/audit/ -type f -mtime +14 -deleteCode language: JavaScript (javascript)

C’est souvent plus raisonnable que vider tout le répertoire, surtout si vous devez garder un minimum d’historique pour analyser les blocages ou faux positifs.

Éviter les suppressions catastrophiques avec des variables

Si vous utilisez une variable dans un script Bash, protégez-vous contre les variables vides.

Mauvaise idée :

LOG_DIR=""

find "$LOG_DIR" -mindepth 1 -deleteCode language: JavaScript (javascript)

Bonne approche :

LOG_DIR="/home/logs"

if [ -z "$LOG_DIR" ] || [ ! -d "$LOG_DIR" ]; then
    echo "Répertoire invalide: $LOG_DIR" >&2
    exit 1
fi

find "$LOG_DIR" -mindepth 1 -deleteCode language: PHP (php)

Version encore plus stricte avec un garde-fou sur le chemin attendu :

LOG_DIR="/home/logs"

case "$LOG_DIR" in
    /home/logs|/home/logs/*)
        find "$LOG_DIR" -mindepth 1 -delete
        ;;
    *)
        echo "Refus de supprimer un chemin non autorisé: $LOG_DIR" >&2
        exit 1
        ;;
esacCode language: JavaScript (javascript)

Dans un script de maintenance, ce genre de garde-fou vaut largement ses trois lignes. Le jour où une variable est vide, vous serez ravi de les avoir écrites.

Alternative avec rm pour vider un dossier

Si vous voulez utiliser rm, cette commande supprime les fichiers visibles et cachés dans un dossier Bash, sans supprimer le dossier parent :

rm -rf /home/logs/{*,.[!.]*,..?*}

Elle couvre :

  • * : les fichiers visibles ;
  • .[!.]* : les fichiers cachés classiques ;
  • ..?* : les fichiers cachés commençant par deux points ou plus.

Mais cette syntaxe est moins lisible, plus dépendante du shell, et plus facile à rater. Pour un usage serveur, je préfère find.

Gérer les très gros répertoires

Dans un répertoire contenant des centaines de milliers ou des millions de fichiers, find ... -delete reste souvent plus fiable qu’un rm -rf *.

Vous pouvez suivre le volume avant suppression avec :

du -sh /home/logs/
find /home/logs/ -mindepth 1 | wc -l

Et après suppression :

du -sh /home/logs/
find /home/logs/ -mindepth 1 | wc -l

Si le dossier est utilisé par un service actif, vérifiez aussi que le service n’écrit pas pendant la suppression, ou que les permissions restent correctes après nettoyage.

Attention aux fichiers ouverts par un processus

Sous Linux, supprimer un fichier ne libère pas toujours immédiatement l’espace disque si un processus garde encore le fichier ouvert.

Pour vérifier les fichiers supprimés mais encore ouverts :

sudo lsof +L1

Si un gros fichier supprimé reste ouvert par Apache, nginx, PHP-FPM, MySQL ou un autre service, il faudra redémarrer ou recharger le service concerné pour libérer l’espace.

Exemple pour Apache :

sudo systemctl reload apache2

Exemple pour nginx :

sudo systemctl reload nginx

Créer une commande de nettoyage réutilisable

Pour éviter les erreurs de copier-coller, vous pouvez créer une petite fonction Bash interactive.

empty_dir() {
    local target="${1:-}"

    if [ -z "$target" ] || [ ! -d "$target" ]; then
        echo "Usage: empty_dir /chemin/du/repertoire" >&2
        return 1
    fi

    echo "Contenu qui sera supprimé dans: $target"
    find "$target" -mindepth 1 -maxdepth 1 -print

    printf "Confirmer la suppression ? [y/N] "
    read -r answer

    case "$answer" in
        y|Y|yes|YES)
            find "$target" -mindepth 1 -delete
            ;;
        *)
            echo "Annulé."
            ;;
    esac
}Code language: PHP (php)

Utilisation :

empty_dir /home/logs

Pour un script automatisé, retirez l’interaction et ajoutez plutôt des garde-fous stricts sur les chemins autorisés.

Résumé rapide

Pour vider un répertoire sans supprimer le dossier parent :

find /home/logs/ -mindepth 1 -deleteCode language: JavaScript (javascript)

Pour voir ce qui sera supprimé :

find /home/logs/ -mindepth 1 -printCode language: PHP (php)

Pour supprimer aussi le dossier parent :

find /home/logs/ -deleteCode language: JavaScript (javascript)

Pour supprimer uniquement les fichiers de plus de 30 jours :

find /home/logs/ -type f -mtime +30 -deleteCode language: JavaScript (javascript)

Pour nettoyer le répertoire d’audit mod_security mentionné dans ma configuration :

sudo find /var/asl/data/audit/ -mindepth 1 -deleteCode language: JavaScript (javascript)

Conclusion

Pour supprimer tous les fichiers et sous-répertoires d’un dossier en Bash, la commande la plus propre est souvent :

find /chemin/du/dossier/ -mindepth 1 -deleteCode language: JavaScript (javascript)

-mindepth 1 protège le répertoire parent. -delete supprime tout ce que find trouve à l’intérieur.

Pour un répertoire de logs, de cache ou d’audit, cette méthode est rapide, fiable et facile à adapter. Prévisualisez avec -print, vérifiez le chemin, puis seulement ensuite supprimez.

Bash fait exactement ce qu’on lui demande. Le sport, c’est de lui demander exactement la bonne chose.

Sources utiles

Gravatar for Matt Biscay

Je suis Matt Biscay, développeur WordPress & WooCommerce certifié chez Codeable, administrateur système et enseignant.

J’aide les entreprises à créer, optimiser et fiabiliser leurs sites WordPress avec une approche technique propre : performance, sécurité, maintenance, développement sur mesure et résolution de problèmes complexes.

Sur Skyminds, je partage des tutoriels WordPress, WooCommerce, Linux et administration système, avec des solutions testées sur des cas réels et pensées pour durer.

Découvrez mes services WordPress et WooCommerce.

1 pensée sur “Bash : supprimer tous les fichiers et sous-répertoires d’un répertoire avec find”

Opinions