web-dev-qa-db-fra.com

Comment supprimer des dossiers contenant n fichiers ou moins?

Je dois effectuer un nettoyage de dossier et je souhaite supprimer les répertoires contenant 10 fichiers ou moins. J'ai essayé de regarder find de GNU, mais rien ne concernait le nombre de fichiers dans un répertoire. Quelles commandes devrais-je utiliser pour accomplir cela?

7
user570992

Une solution consisterait à utiliser l'action -exec de find pour exécuter un test personnalisé du nombre de fichiers.

On pourrait utiliser une seconde commande find avec wc pour rechercher et compter les fichiers dans chaque répertoire, mais une meilleure option consisterait probablement pour Shell qui insère les noms de fichiers dans un tableau, puis renvoie un fichier logique. valeur indiquant si la taille du tableau est inférieure au seuil, c'est-à-dire.

files=( dir/* ); ((${#files[@]} < 10))

En réunissant tout cela, nous devrions pouvoir répertorier tous les sous-répertoires contenant moins de 10 fichiers (y compris les sous-sous-répertoires) en utilisant

find . -depth -type d ! -name '.' -exec bash -c '
  shopt -s nullglob; files=( "$1"/* ); ((${#files[@]} < ${2:-10}))
  ' bash {} 10 \; -print0 | xargs -0

(vous pouvez ajuster le nombre 10 après le bash {} pour différents seuils - le paramètre de développement ${2:-10} le fait passer à 10 fichiers par défaut si aucun second argument n'est fourni). Par exemple, étant donné

$ tree .
.
├── bar
│   ├── file1
│   ├── file2
│   ├── file3
│   ├── file4
│   ├── file5
│   ├── file6
│   ├── file7
│   ├── file8
│   ├── file9
│   └── other file
├── baz
│   ├── other file
│   └── subdir
└── foo
    └── somefile

4 directories, 12 files

ensuite

find . -depth -type d ! -name '.' -exec bash -c '
  shopt -s nullglob; files=( "$1"/* ); ((${#files[@]} < "${2:-10}"))
  ' bash {} 10 \; -print0 | xargs -0
./foo ./baz/subdir ./baz

Si cela semble être la bonne chose, vous pouvez réellement les supprimer en ajoutant rm -rfmais soyez très prudent avec cela - souvenez-vous qu'il n'y a pas de 'défaire'

find . -depth -type d ! -name '.' -exec bash -c '
  shopt -s nullglob; files=( "$1"/* ); ((${#files[@]} < ${2:-10}))
' bash {} 10 \; -print0 | xargs -0 rm -rf

(La xargs pourrait être éliminée en utilisant une autre action -exec pour exécuter rm plus directement, mais la formulation ci-dessus facilite la généralisation - impression, stat, suppression ou autre.)

Notez que cela agira de manière récursive, c’est-à-dire qu’un répertoire contenant initialement plus de n fichiers , y compris les sous-répertoires , peut être supprimé à la suite de certains de ces sous-répertoires. étant eux-mêmes supprimés en tant que find sauvegarde l'arborescence de répertoires - le répertoire en cours est explicitement protégé contre toute suppression éventuelle par le test ! -name '.'.

Si vous n'avez pas en avez besoin pour agir de manière récursive, vous pouvez simplement parcourir les répertoires et effectuer le même nombre de fichiers et la même logique de test, par exemple. supprimer tous les répertoires de premier niveau contenant moins de 10 fichiers dans le répertoire en cours

shopt -s nullglob
for d in */; do
  files=( "$d"/* )
  ((${#files[@]} < 10)) && echo rm -rf -- "$d"
done 
3
steeldriver

Je n'ai pas complètement testé cela, mais cela devrait fonctionner. Vous pouvez également utiliser find pour accomplir cela.

# Loop over all files
for dir in * **/*; do
    # Make sure this is a directory
    if [ -d "${dir}" ]; then
        # Get the number of files (not including directories) in this directory
        FILE_COUNT=`ls $dir -1 | grep -v / | wc -l`
        # Check if it's less than 10
        if [ $FILE_COUNT -lt 10 ]; then
            # Delete the directory
            rm -rf "${dir}"
        fi
    fi
done
0
rymac