Réponses:
Voici une approche complètement différente basée sur GNU find
et uniq
. C'est beaucoup plus rapide et beaucoup plus convivial que les réponses basées sur l'exécution d'une commande shell qui compte les fichiers pour chaque répertoire trouvé.
find . -type f -printf '%h\n' | sort | uniq -d
La find
commande imprime le répertoire de tous les fichiers de la hiérarchie et uniq
n'affiche que les répertoires qui apparaissent au moins deux fois.
-printf '%h\0' | sort -z | uniq -zd | xargs -r0 ...
find . -type d \
-exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' \
-print
Cela trouvera tous les noms dans ou sous le répertoire courant, puis filtrera tous les noms qui ne sont pas des noms de répertoires.
Les noms de répertoire restants seront donnés à ce court script:
c=0
for n in "$1"/*; do
[ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done
[ "$c" -ge 2 ]
Ce script comptera le nombre de fichiers normaux (en sautant les liens symboliques) dans le répertoire donné comme premier argument de ligne de commande (à partir de find
). La dernière commande du script est un test pour voir si le nombre était de 2 ou plus. Le résultat de ce test est la valeur de retour (état de sortie) du script.
Si le test a réussi, -print
entraînera l' find
impression du chemin d'accès au répertoire.
Pour également considérer les fichiers cachés (fichiers dont les noms commencent par un point), changez le sh -c
script de dire
for n in "$1"/*; do
à
for n in "$1"/* "$1"/.*; do
Essai:
$ tree
.
`-- test
|-- a
|-- dir1
| |-- a
| |-- b
| `-- c
`-- dir2
|-- dira
|-- dirb
| |-- file-1
| `-- file-2
`-- dirc
6 directories, 6 files
$ find . -type d -exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' -print
./test/dir1
./test/dir2/dirb
[ "" -ge 2 ]
c'est un test valide.
dash
, bash --posix
et test
tous affichent un message d'erreur et quittent avec 2 (c.-à-d. "Une erreur s'est produite")
ksh
fonctionnant sous le nom de mas sh
. Se modifiera immédiatement. Merci de m'avoir piqué! :-)
[ -f ... ]
déréférence les liens symboliques. Vous devez ajouter un test pour les éliminer car la question spécifie que seuls les fichiers normaux doivent être comptés.
Avec l'aide de la réponse de Gilles sur SU et son revers et quelques modifications, voici ce dont vous avez besoin.
find . -type d -exec sh -c 'set -- "$1"/*;X=0;
for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print
Arborescence de répertoires.
.
├── test
│ ├── dir1
│ │ ├── a
│ │ ├── b
│ │ └── c
│ ├── dir2
│ │ ├── dira
│ │ │ └── a file\012with\012multiple\012line
│ │ ├── dirb
│ │ │ ├── file-1
│ │ │ └── file-2
│ │ └── dirc
│ ├── diraa
│ ├── dirbb
│ ├── dircc
│ └── x
│ └── x1
│ └── x2
└── test2
├── dir3
└── dir4
Résultat:
./test
./test/dir1
./test/dir2/dirb
test
et les dir2
répertoires dans ma configuration de test (voir ma réponse).
test/x1
et en test/x2
tant que fichiers également ... $1
et $2
seront des répertoires pour test
, et le répertoire sera manqué.
Une autre approche find
+ wc
:
find path/currdir -maxdepth 1 -type d ! -empty ! -path "path/currdir" \
-exec sh -c 'count=$(find "$1" -maxdepth 1 -type f | wc -l); [ $count -ge 2 ]' _ {} \; -print
path/currdir
- chemin vers votre répertoire actuel
-maxdepth 1
- ne considérer que les sous-dossiers enfants directs
! -empty
- ignorer les sous-dossiers vides
! -path "path/currdir"
- ignorer le chemin du répertoire courant
count=$(find "$1" -maxdepth 1 -type f | wc -l)
- count
est attribué avec le nombre de fichiers pour chaque sous-dossier trouvé
[ $count -ge 2 ] ... -print
- imprimer le nom / chemin du sous-dossier contenant 2 fichiers réguliers ou plus
find
. Dans ce cas, parce que GNUfind
va modifier les noms des répertoires qui ont des caractères qui ne sont pas imprimables dans les paramètres régionaux actuels (comme "ä" dans les paramètres régionaux C). Voir aussi unix.stackexchange.com/questions/321697/…