Pada dasarnya ada 2 metode yang dapat Anda gunakan untuk melakukan ini. Satu akan mengurai string sedangkan yang lain akan beroperasi pada setiap file. Parsing string menggunakan alat seperti grep, sed, atau awkjelas akan lebih cepat tapi di sini adalah contoh yang menunjukkan keduanya, serta bagaimana Anda bisa "profil" 2 metode.
Contoh data
Untuk contoh di bawah ini kami akan menggunakan data berikut
$ 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}
Hapus beberapa *f*file dari dir1/*:
$ rm dir1/dir10{0..2}/*f*
Approach # 1 - Parsing via string
Di sini kita akan menggunakan alat-alat berikut, find, grep, dan sort.
$ find . -type f -name '*f*' | grep -o "\(.*\)/" | sort -u | head -5
./dir1/dir103/
./dir1/dir104/
./dir1/dir105/
./dir1/dir106/
./dir1/dir107/
Approach # 2 - Parsing menggunakan file
Rantai alat yang sama seperti sebelumnya, kecuali kali ini kami akan menggunakan dirnamebukan grep.
$ find . -type f -name '*f*' -exec dirname {} \; | sort -u | head -5
./dir1/dir103
./dir1/dir104
./dir1/dir105
./dir1/dir106
./dir1/dir107
CATATAN: Contoh di atas hanya digunakan head -5untuk membatasi jumlah output yang kita hadapi untuk contoh-contoh ini. Biasanya akan dihapus untuk mendapatkan daftar lengkap Anda!
Membandingkan hasilnya
Kita dapat menggunakan timeuntuk melihat 2 pendekatan.
dirname
real 0m0.372s
user 0m0.028s
sys 0m0.106s
grep
real 0m0.012s
user 0m0.009s
sys 0m0.007s
Jadi selalu yang terbaik untuk berurusan dengan string jika memungkinkan.
Metode penguraian string alternatif
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
uniqke dalam campuran sangat membantu dengan menghapus garis berulang yang sudah tepat bersebelahan.find . -type f -name '*f*' -printf '%h\0' | uniq -z | sort -zu | tr '\0' '\n'. Atau jika alat Anda sedikit lebih tua, maka uniq mungkin tidak memiliki opsi -z.find . -type f -name '*f*' -printf '%h\n' | uniq | sort -u