Volevo solo sottolineare che lo gnu uniq
sembra terribilmente lento, anche in un elenco ordinato.
Ho appena provato a ottenere un elenco di prefissi di directory da un elenco di nomi di file ordinati:
$ pv all_files | cut -d '/' -f 1,2,3,4 | uniq > all_prefixes
36.7GiB 0:07:41 [81.4MiB/s]
$ pv all_files | cut -d '/' -f 1,2,3,4 | sort -u > all_prefixes2
36.7GiB 0:03:14 [ 193MiB/s]
$ pv all_files | cut -d '/' -f 1,2,3,4 | awk '!x[$0]++' > all_prefixes3
36.7GiB 0:02:18 [ 270MiB/s]
sort -u sembra due volte più veloce di uniq, e questo è con l'ordinamento in lettura da stdin e la scrittura in stdout, quindi non vedo che faccia ancora parallelismi. Non ho idea del perché uniq dovrebbe essere molto più lento dell'ordinamento, dal momento che non deve ordinare l'elenco ...
L'outpuf di questo comando è molto piccolo (ci sono molti duplicati), solo 264kb e l'ordinamento termina immediatamente dopo che pv è stato fatto.
Le stesse velocità rimangono se si gira intorno all'ordine dei comandi, il mio flusso è limitato dal tempo della CPU qui, non dall'accesso al disco e dalla cache (ho solo 8 GB di RAM e il mio scambio non viene utilizzato)
Sto eseguendo questo su una macchina fedora 31 con gnu coreutils sort e uniq e gnu awk; la locale è impostata su en_US.UTF-8
AGGIORNAMENTO , dal momento che questo mi ha incuriosito un po 'ho fatto qualche altro test, cerchiamo di eliminare la parte tagliata e assicuriamoci che il file sia ben ordinato
cat all_files | cut -d '/' -f 1,2,3,4 | sort -T . > test
Questo richiede 8.4 minuti. il test ora è grande 7,9 GB
eseguiamo questi strumenti sul file invece che in una pipe, questo consentirà a questi strumenti di fare qualche ottimizzazione, come sort multi thread. e anche da un ssd più veloce.
Potresti non notare che anche l'ordinamento sta occupando molta memoria, dal momento che fa trucchi intelligenti con file temporanei in / tmp che potrebbero essere tmpfs e saranno nel tuo ram (prova a ordinare un file più grande di / tmp, corri nello spazio problemi, ecco perché ho bisogno del flag -T nel comando sopra)
$ time sort -u test > /dev/null
339.24user 3.54system 1:28.87elapsed 385%CPU (0avgtext+0avgdata 2365856maxresident)k
9555544inputs+0outputs (0major+591298minor)pagefaults 0swaps
$ time awk '!x[$0]++' test > /dev/null
51.15user 1.55system 0:52.94elapsed 99%CPU (0avgtext+0avgdata 10976maxresident)k
0inputs+0outputs (0major+1923minor)pagefaults 0swaps
$ time uniq test > /dev/null
421.89user 2.76system 7:06.63elapsed 99%CPU (0avgtext+0avgdata 1980maxresident)k
52712inputs+0outputs (0major+79minor)pagefaults 0swaps
Quindi sembra che la tua soluzione Awk sia la più veloce di queste 3 e utilizzi effettivamente meno memoria
update2
e ora con una localizzazione più semplice
$ export LC_ALL=c
$ time sort -u test > /dev/null 1.2m ? Tue Apr 21 17:09:22 2020
119.18user 3.64system 0:38.24elapsed 321%CPU (0avgtext+0avgdata 2013472maxresident)k
$ time awk '!x[$0]++' test > /dev/null 1161ms ? Tue Apr 21 17:07:31 2020
67.23user 2.50system 1:10.16elapsed 99%CPU (0avgtext+0avgdata 10480maxresident)k
7187520inputs+0outputs (0major+1912minor)pagefaults 0swaps
$ time uniq test > /dev/null
22.05user 2.02system 0:24.24elapsed 99%CPU (0avgtext+0avgdata 1488maxresident)k
2959648inputs+0outputs (1major+72minor)pagefaults 0swaps
Questa volta uniq vince la gara ... come accennato da Stéphane Chazelas nei commenti, impostare il locale su C rende più veloce l'ordinamento e l'unicità!
time
?