Antworten:
Hier ist ein völlig anderer Ansatz basierend auf GNU find
und uniq
. Dies ist viel schneller und viel CPU-freundlicher als Antworten, die auf der Ausführung eines Shell-Befehls basieren, der Dateien für jedes gefundene Verzeichnis zählt.
find . -type f -printf '%h\n' | sort | uniq -d
Der find
Befehl druckt das Verzeichnis aller Dateien in der Hierarchie und uniq
zeigt nur die Verzeichnisse an, die mindestens zweimal angezeigt werden.
-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
Dadurch werden alle Namen im oder unter dem aktuellen Verzeichnis gefunden und anschließend alle Namen herausgefiltert, die keine Namen von Verzeichnissen sind.
Die verbleibenden Verzeichnisnamen werden diesem kurzen Skript zugewiesen:
c=0
for n in "$1"/*; do
[ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done
[ "$c" -ge 2 ]
Dieses Skript zählt die Anzahl der regulären Dateien (Überspringen symbolischer Links) in dem Verzeichnis, das als erstes Befehlszeilenargument (von find
) angegeben wurde. Der letzte Befehl im Skript ist ein Test, um festzustellen, ob die Anzahl 2 oder höher war. Das Ergebnis dieses Tests ist der Rückgabewert (Exit-Status) des Skripts.
Wenn der Test erfolgreich war, -print
wird find
der Pfad zum Verzeichnis ausgedruckt.
Um auch versteckte Dateien (Dateien, deren Namen mit einem Punkt beginnen) zu berücksichtigen, ändern Sie das sh -c
Skript von "sagen"
for n in "$1"/*; do
zu
for n in "$1"/* "$1"/.*; do
Testen:
$ 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 ]
ein gültiger Test ist.
dash
, bash --posix
Und test
alle Display eine Fehlermeldung und Ausgang mit 2 (dh „Ein Fehler ist aufgetreten“)
ksh
das als läuft sh
. Wird sofort geändert. Danke, dass du mich angestupst hast! :-)
[ -f ... ]
dereferenziert symbolische Links. Sie sollten einen Test hinzufügen, um sie zu beseitigen, da die Frage angibt, dass nur reguläre Dateien gezählt werden sollen.
Mit Hilfe von Gilles 'Antwort auf SU und seiner Umkehrung und einigen Modifikationen, hier was Sie brauchen.
find . -type d -exec sh -c 'set -- "$1"/*;X=0;
for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print
Verzeichnisbaum.
.
├── 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
Ergebnis:
./test
./test/dir1
./test/dir2/dirb
test
als auch das dir2
Verzeichnis in meinem Testaufbau (siehe meine Antwort).
test/x1
und test/x2
als Dateien hinzu ... $1
und $2
werden Verzeichnisse für test
, und das Verzeichnis wird übersehen.
Ein weiterer find
+ wc
Ansatz:
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
- Pfad zu Ihrem aktuellen Verzeichnis
-maxdepth 1
- Berücksichtigen Sie nur direkte untergeordnete Unterordner
! -empty
- leere Unterordner ignorieren
! -path "path/currdir"
- Ignorieren Sie den aktuellen Verzeichnispfad
count=$(find "$1" -maxdepth 1 -type f | wc -l)
- count
wird mit der Anzahl der Dateien für jeden gefundenen Unterordner zugewiesen
[ $count -ge 2 ] ... -print
- Drucken Sie den Namen / Pfad des Unterordners, der 2 oder mehr reguläre Dateien enthält
find
. In diesem Fall, weil GNUfind
die Namen von Verzeichnissen mit Zeichen entstellt, die im aktuellen Gebietsschema nicht druckbar sind (wie "ä" im Gebietsschema C). Siehe auch unix.stackexchange.com/questions/321697/…