trova tutte le sottodirectory finali in un albero


11

data la seguente struttura:

oz123@debian:~/ $ tree .
.
├── a
│   ├── a1
│   ├── a2
│   └── a3
├── a1
│   ├── a11
│   ├── a12
│   └── a31
├── b
│   └── b1
│       ├── b11
│       │   └── b21
│       │       └── b31
│       ├── b12
│       └── b3
└── c

16 directories, 0 files

Come trovo tutti i nodi finali?

Ho trovato le seguenti soluzioni che sembrano essere buone, ma devo provare che non esiste un caso di test che fallirà.

La pagina di aiuto degli -linksstati:

Puoi anche cercare file con un certo numero di collegamenti, con '-link'. Le directory normalmente hanno almeno due hard link; loro . l'ingresso è il secondo. Se hanno delle sottodirectory, ognuna di queste ha anche un hard link chiamato ... alla sua directory principale. Il . e .. le voci della directory non vengono normalmente cercate a meno che non siano menzionate nella riga di comando find.

possibile soluzione:

oz123@debian:~/ $ find .  -type d  -links 2
./a/a2
./a/a3
./a/a1
./c
./a1/a31
./a1/a11
./a1/a12
./b/b1/b12
./b/b1/b3
./b/b1/b11/b21/b31
  • Qualcuno può fornire una soluzione migliore (senza usare pipe e sed, questo è stato performante ...)
  • Funzionerà su qualsiasi filesystem?

3
Non troverai più performante del -links 2trucco. Non funzionerà btrfs.
Stéphane Chazelas,

Risposte:


3

Come aggiunta alla propria soluzione con -links, voglio solo aggiungere che non funzionerà su filesystem che non seguono la convenzione di collegamento directory Unix. Da questa man findopzione -noleafsono almeno CD-ROM, filesystem MS-DOS e punti di montaggio del volume AFS.

Per riferimento, questa domanda è stata già discussa con diverse soluzioni che sono effettivamente più lente e di solito ricorrono alle connessioni a sed / awk e simili.


3

C'è un'opzione un po 'più ovvia -empty:

find . -type d -empty

Agg. Ok, hai ragione in questo modo non funzionerà con i file in dirs.

Quindi qui è una versione non affidabile del file system fisso:

find dtest/ -type d -exec sh -c "if [ \$(find {} -maxdepth 1 -type d | wc -l) -eq 1 ]; then echo {} ; fi" \;

2
Se capisco la domanda, le directory finali potrebbero contenere file. Questo non avrebbe stampato quelle directory in quanto non sarebbero "vuote" ...
Stefan

@rush, subdirs può essere vuoto o no
Oz123

@ Oz123, controlla il mio aggiornamento, dovrebbe essere abbastanza veloce, ma un po 'più lento rispetto alla tua strada.
corsa il

@rush, grazie, ma ho davvero bisogno di evitare i tubi, possono rendere le cose più lente.
Oz123,

1

find . -type d -links 2funziona sulla maggior parte dei filesystem, ma non su tutti. Non penso che ci sia un modo per sapere se non sapere quali tipi di filesystem hanno la proprietà che le directory contengano un collegamento a se stesse. GNU find lo rileva dinamicamente (se stampa qualcosa su "Attivare automaticamente l'opzione -noleaf di find", sai che il tuo filesystem non ha questa proprietà). I tipi di filesystem più comuni sono ok, ma non FAT o btrfs.

Se vuoi essere sicuro, dovrai testare ogni directory. Un modo per farlo è richiamare di findnuovo per ogni sottodirectory.

find . -type d ! -exec sh -c '
   find "$1/." ! -name . -type d -prune | grep -q "^"' sh {} \; -print

(con GNU find, puoi sostituirlo -prunecon -print -quitper renderlo un po 'più efficiente).

Un altro modo è post-processare l'output di find. Con find -depth, una directory foglia è quella che non segue una sottodirectory di se stessa.

find . -depth -type d -print0 |
awk -v RS='\0' '
    substr(previous, 1, length($0) + 1) != $0 "/"
    { previous = $0 }
'

0

Prova la seguente soluzione (dovrebbe essere compatibile Linux, Unix e OS X):

find . -type d -execdir sh -c 'test -z "$(find "{}" -mindepth 1 -type d)" && echo $PWD/{}' ';'

È un approccio simile alla soluzione rush , ma senza tubi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.