Risposte:
Ecco un approccio completamente diverso basato su GNU finde uniq. Questo è molto più veloce e molto intuitivo per la CPU rispetto alle risposte basate sull'esecuzione di un comando shell che conta i file per ogni directory trovata.
find . -type f -printf '%h\n' | sort | uniq -d
Il findcomando stampa la directory di tutti i file nella gerarchia e uniqvisualizza solo le directory che appaiono almeno due volte.
-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
Questo troverà tutti i nomi dentro o sotto la directory corrente e quindi filtrerà tutti i nomi che non sono nomi di directory.
I nomi di directory rimanenti verranno assegnati a questo breve script:
c=0
for n in "$1"/*; do
[ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done
[ "$c" -ge 2 ]
Questo script conterà il numero di file regolari (saltando i collegamenti simbolici) nella directory indicata come primo argomento della riga di comando (da find). L'ultimo comando nello script è un test per vedere se il conteggio era 2 o maggiore. Il risultato di questo test è il valore restituito (stato di uscita) dello script.
Se il test ha esito positivo, -printverrà findstampato il percorso della directory.
Per considerare anche i file nascosti (file il cui nome inizia con un punto), cambia lo sh -cscript dal dire
for n in "$1"/*; do
per
for n in "$1"/* "$1"/.*; do
test:
$ 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 ]è un test valido.
dash, bash --posixE testtutte le visualizzazione di un messaggio di errore ed esce con 2 (vale a dire "l'errore è verificato un")
kshfunziona come sh. Si modificherà immediatamente. Grazie per avermi beccato! :-)
[ -f ... ]dereferenze collegamenti simbolici. È necessario aggiungere un test per eliminarli poiché la domanda specifica che devono essere conteggiati solo i file regolari.
Con l'aiuto della risposta di Gilles su SU e il suo rovescio e alcune modifiche, ecco cosa ti serve.
find . -type d -exec sh -c 'set -- "$1"/*;X=0;
for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print
Albero delle directory.
.
├── 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
Risultato:
./test
./test/dir1
./test/dir2/dirb
testla dir2directory nella mia configurazione di test (vedi la mia risposta).
test/x1e anche test/x2come file ... $1e $2saranno directory per test, e la directory ci mancherà.
Un altro approccio 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 - percorso alla directory corrente
-maxdepth 1- considera solo le sottocartelle figlio dirette
! -empty - ignora le sottocartelle vuote
! -path "path/currdir" - ignora il percorso della directory corrente
count=$(find "$1" -maxdepth 1 -type f | wc -l)- countè assegnato con il numero di file per ogni sottocartella trovata
[ $count -ge 2 ] ... -print - stampa il nome / percorso della sottocartella contenente 2 o più file regolari
find. In questo caso, poiché GNUfindmanipolerà i nomi delle directory che hanno caratteri che non sono stampabili nella locale corrente (come "ä" nella locale C). Vedi anche unix.stackexchange.com/questions/321697/…