Unix – Seuls les répertoires contenant un sous-répertoire

Comment puis-je imprimer dans le shell Unix le nombre de répertoires dans une arborescence contenant d’autres répertoires?

Je n’ai pas encore trouvé de solution avec des commandes comme find ou ls .

Si vous générez une liste de tous les répertoires sous un répertoire particulier, puis supprimez le dernier composant du nom, vous avez une liste des répertoires contenant des sous-répertoires, mais il est probable que des répétitions figurent dans cette liste. Donc, vous devez post-traiter la liste, en obtenant (en première approximation):

 find ${base:-.} -type d | sed 's%/[^/]*$%%' | sort -u 

Recherchez tous les répertoires sous le répertoire ou les répertoires répertoriés dans la variable $base , par défaut dans le répertoire en cours, et imprimez leurs noms. Le code suppose que vous n’avez pas de répertoires avec une nouvelle ligne dans le nom. Si vous le faites, il existe des correctifs, mais la meilleure solution consiste à renommer le répertoire. La commande sed supprime le dernier slash et tout ce qui suit. Le sorting élimine les entrées en double. Ce qui rest est la liste des répertoires contenant des sous-répertoires.

Eh bien, plus ou moins. Il y a le cas dégénéré à prendre en compte: les répertoires de niveau supérieur de la liste seront listés qu’ils aient ou non des sous-répertoires. La réparation est un peu plus difficile. Vous devez éliminer toutes les lignes de sortie correspondant exactement aux répertoires spécifiés avant de supprimer les éléments de fin. Donc, vous avez besoin de quelque chose comme:

 { printf '\\#^%s$#d\n' ${base:-.} echo 's%/[^/]*$%%' } > sed.script find ${base:-.} -type d | sed -f sed.script | sort -u rm -f sed.script 

Le \\#^%s$#d suppose que vous n’utilisez pas # dans les noms de répertoire. Si vous l’utilisez, vous devez trouver un caractère que vous n’utilisez pas dans les noms (peut-être Control-A) et l’utiliser à la place du # . Si vous pouviez faire face à n’importe quel caractère, vous devrez faire plus de travail en évitant un caractère obscur, tel que Control-A, lorsqu’il apparaît dans un nom de répertoire.

Il y a toujours un problème: utiliser un nom fixe comme sed.script pour un nom de fichier temporaire est mauvais (pour plusieurs raisons – par exemple, deux personnes essayant d’exécuter le script en même temps dans le même répertoire, même si cela peut aussi être une sécurité). risk), utilisez mktemp pour créer un nom de fichier temporaire:

 tmp=$(mktemp ${TMPDIR:-/tmp}/dircnt.XXXXXX) trap "rm -f $tmp; exit 1" 0 1 2 3 13 15 { printf '\\#^%s$#d\n' ${base:-.} echo 's%/[^/]*$%%' } > $tmp find ${base:-.} -type d | sed -f $tmp | sort -u rm -f $tmp trap 0 

Cela traite les signaux les plus courants (HUP, INT, QUIT, PIPE, TERM) et supprime le fichier temporaire même si l’un de ceux-ci arrive.

Clairement, si vous voulez simplement compter le nombre de répertoires, vous pouvez diriger la sortie des commandes ci-dessus vers wc -l pour obtenir le compte.

Vous pouvez utiliser la commande find . -type d -not -empty : find . -type d -not -empty find . -type d -not -empty

Cela imprimera tous les sous-répertoires qui ne sont pas vides. Vous pouvez contrôler la profondeur de la recherche avec -maxdepth .

Pour imprimer le numéro, vous pouvez utiliser wc -l .

 find . -type d -not -empty | wc -l 
 ls -1d */*/. | cut -d / -f1 | uniq