Ci sono essenzialmente 2 metodi che puoi usare per farlo. Uno analizzerà la stringa mentre l'altro opererà su ciascun file. L'analisi della stringa utilizza uno strumento come grep, sedo awksarà ovviamente più veloce, ma ecco un esempio che mostra entrambi, oltre a come "profilare" i 2 metodi.
Dati di esempio
Per gli esempi seguenti utilizzeremo i seguenti dati
$ touch dir{1..3}/dir{100..112}/file{1..5}
$ touch dir{1..3}/dir{100..112}/nile{1..5}
$ touch dir{1..3}/dir{100..112}/knife{1..5}
Elimina alcuni *f*file da dir1/*:
$ rm dir1/dir10{0..2}/*f*
Approccio n. 1 - Analisi tramite stringhe
Qui stiamo andando a utilizzare i seguenti strumenti, find, grep, e sort.
$ find . -type f -name '*f*' | grep -o "\(.*\)/" | sort -u | head -5
./dir1/dir103/
./dir1/dir104/
./dir1/dir105/
./dir1/dir106/
./dir1/dir107/
Approccio n. 2: analisi tramite file
Stessa catena di strumenti di prima, tranne che questa volta useremo dirnameinvece di grep.
$ find . -type f -name '*f*' -exec dirname {} \; | sort -u | head -5
./dir1/dir103
./dir1/dir104
./dir1/dir105
./dir1/dir106
./dir1/dir107
NOTA: gli esempi sopra riportati stanno head -5semplicemente limitando la quantità di output con cui abbiamo a che fare con questi esempi. Normalmente verrebbero rimossi per ottenere il tuo elenco completo!
Confronto dei risultati
Possiamo usare timeper dare un'occhiata ai 2 approcci.
dirname
real 0m0.372s
user 0m0.028s
sys 0m0.106s
grep
real 0m0.012s
user 0m0.009s
sys 0m0.007s
Quindi, se possibile, è sempre meglio occuparsi delle stringhe.
Metodi alternativi di analisi delle stringhe
grep & PCRE
$ find . -type f -name '*f*' | grep -oP '^.*(?=/)' | sort -u
sed
$ find . -type f -name '*f*' | sed 's#/[^/]*$##' | sort -u
awk
$ find . -type f -name '*f*' | awk -F'/[^/]*$' '{print $1}' | sort -u
uniqnel mix aiuta molto rimuovendo le linee ripetute che sono già una accanto all'altra.find . -type f -name '*f*' -printf '%h\0' | uniq -z | sort -zu | tr '\0' '\n'. Oppure, se i tuoi strumenti sono un po 'più vecchi, uniq potrebbe non avere l'opzione -z.find . -type f -name '*f*' -printf '%h\n' | uniq | sort -u