Sur une machine Linux, j'aimerais parcourir une hiérarchie de dossiers et obtenir une liste de toutes les extensions de fichiers distinctes qui s'y trouvent.
Quel serait le meilleur moyen d'y parvenir à partir d'un shell?
Essayez ceci (vous ne savez pas si c'est le meilleur moyen, mais ça marche):
find . -type f | Perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
Cela fonctionne comme suit:
Pas besoin du tuyau pour sort
, awk peut tout faire:
find . -type f | awk -F. '!a[$NF]++{print $NF}'
Version récursive:
find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u
Si vous voulez des totaux (combien de fois l'extension a été vue):
find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort | uniq -c | sort -rn
Non récursif (dossier unique):
for f in *.*; do printf "%s\n" "${f##*.}"; done | sort -u
J'ai basé ceci sur cet article de forum , le crédit devrait y aller.
Powershell:
dir -recurse | select-object extension -unique
Merci à http://kevin-berridge.blogspot.com/2007/11/windows-powershell.html
Tout trouver avec un point et ne montrer que le suffixe.
find . -type f -name "*.*" | awk -F. '{print $NF}' | sort -u
si vous connaissez tous les suffixes ont 3 caractères puis
find . -type f -name "*.???" | awk -F. '{print $NF}' | sort -u
ou avec sed affiche tous les suffixes de un à quatre caractères. Remplacez {1,4} par la plage de caractères attendue dans le suffixe.
find . -type f | sed -n 's/.*\.\(.\{1,4\}\)$/\1/p'| sort -u
Ajout de ma propre variation au mélange. Je pense que c'est le plus simple du lot et peut être utile lorsque l'efficacité n'est pas une préoccupation majeure.
find . -type f | grep -o -E '\.[^\.]+$' | sort -u
Mon alternative à awk-less, sed-less, Perl less, pythonless et moins Python:
find . -type f | rev | cut -d. -f1 | rev | tr '[:upper:]' '[:lower:]' | sort | uniq --count | sort -rn
L'astuce consiste à inverser la ligne et à couper l'extension au début.
Il convertit également les extensions en minuscules.
Exemple de sortie:
3689 jpg
1036 png
610 mp4
90 webm
90 mkv
57 mov
12 avi
10 txt
3 Zip
2 ogv
1 xcf
1 trashinfo
1 sh
1 m4v
1 jpeg
1 ini
1 gqv
1 gcs
1 dv
Dans Python, utilisez des générateurs pour les très grands répertoires, y compris les extensions vierges, et obtenez le nombre de fois que chaque extension apparaît:
import json
import collections
import itertools
import os
root = '/home/andres'
files = itertools.chain.from_iterable((
files for _,_,files in os.walk(root)
))
counter = collections.Counter(
(os.path.splitext(file_)[1] for file_ in files)
)
print json.dumps(counter, indent=2)
J'ai essayé un tas de réponses ici, même la "meilleure" réponse. Ils ont tous manqué de ce que je recherchais. Donc, à part les 12 dernières heures passées en code regex pour plusieurs programmes et en lisant et testant ces réponses, voici ce que j’ai trouvé qui fonctionne EXACTEMENT comme je le veux.
find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort -u
Si vous avez besoin d’un nombre d’extensions de fichier, utilisez le code ci-dessous
find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort | uniq -c | sort -rn
Bien que ces méthodes prennent un certain temps et qu'elles ne soient probablement pas la meilleure façon de résoudre le problème, elles fonctionnent.
Mise à jour: les extensions de fichier longues par @ alpha_989 poseront un problème. Cela est dû au regex original "[[: alpha:]] {3,6}". J'ai mis à jour la réponse pour y inclure l'expression régulière "[[: alpha:]] {2,16}". Cependant, toute personne utilisant ce code doit savoir que ces chiffres sont les min et max de combien de temps l'extension est autorisée pour la sortie finale. Tout ce qui est en dehors de cette plage sera divisé en plusieurs lignes dans la sortie.
Remarque: le message d'origine était "- Greps pour les extensions de fichier de 3 à 6 caractères (ajustez simplement les chiffres si elles ne correspondent pas à vos besoins). Cela évite les fichiers de cache et les fichiers système (le bit de fichier système sert à effectuer une recherche en prison). "
Idée: Peut être utilisé pour rechercher des extensions de fichier d’une longueur spécifique via:
find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{4,}" | awk '{print tolower($0)}' | sort -u
Où 4 est la longueur des extensions de fichier à inclure, puis trouve également les extensions qui dépassent cette longueur.
Comme il existe déjà une autre solution utilisant Perl:
Si vous avez installé Python, vous pouvez aussi faire (depuis le shell):
python -c "import os;e=set();[[e.add(os.path.splitext(f)[-1]) for f in fn]for _,_,fn in os.walk('/home')];print '\n'.join(e)"
Je ne pense pas que celui-ci a été mentionné pour le moment:
find . -type f -exec sh -c 'echo "${0##*.}"' {} \; | sort | uniq -c
Jusqu'à présent, aucune des réponses n'aborde correctement les noms de fichiers avec les nouvelles lignes (à l'exception de ChristopheD, qui est arrivé juste au moment où je tapais ceci). Ce qui suit n’est pas un one-liner Shell, mais fonctionne et est relativement rapide.
import os, sys
def names(roots):
for root in roots:
for a, b, basenames in os.walk(root):
for basename in basenames:
yield basename
sufs = set(os.path.splitext(x)[1] for x in names(sys.argv[1:]))
for suf in sufs:
if suf:
print suf
Je pense que la manière la plus simple et directe est
for f in *.*; do echo "${f##*.}"; done | sort -u
C'est modifié sur la 3ème voie de ChristopheD.
tu pourrais aussi faire ça
find . -type f -name "*.php" -exec PATHTOAPP {} +