find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort |uniq
Di atas menemukan semua file di bawah direktori saat ini ( .
) yang merupakan file biasa ( -type f
) dan ada f
di suatu tempat di namanya ( -name '*f*'
). Selanjutnya, sed
menghapus nama file, hanya menyisakan nama direktori. Kemudian, daftar direktori diurutkan ( sort
) dan duplikat dihapus ( uniq
).
The sed
perintah terdiri dari pengganti tunggal. Ia mencari kecocokan dengan ekspresi reguler /[^/]+$
dan menggantikan apa pun yang cocok dengan apa pun. Tanda dolar berarti akhir dari garis. [^/]+'
berarti satu atau lebih karakter yang bukan garis miring. Dengan demikian, /[^/]+$
berarti semua karakter dari garis miring terakhir ke baris akhir. Dengan kata lain, ini cocok dengan nama file di akhir path lengkap. Dengan demikian, perintah sed menghapus nama file, tidak mengubah nama direktori tempat file itu berada.
Penyederhanaan
Banyak sort
perintah modern mendukung -u
bendera yang membuatnya uniq
tidak perlu. Untuk sed GNU:
find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort -u
Dan, untuk MacOS sed:
find . -type f -name '*f*' | sed -E 's|/[^/]+$||' |sort -u
Juga, jika find
perintah Anda mendukungnya, dimungkinkan untuk find
mencetak nama direktori secara langsung. Ini menghindari kebutuhan untuk sed
:
find . -type f -name '*f*' -printf '%h\n' | sort -u
Versi lebih kuat (Membutuhkan alat GNU)
Versi di atas akan bingung dengan nama file yang menyertakan baris baru. Solusi yang lebih kuat adalah melakukan pengurutan pada string yang diakhiri NUL:
find . -type f -name '*f*' -printf '%h\0' | sort -zu | sed -z 's/$/\n/'
uniq
ke 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
-E
untuk MacOS.Mengapa tidak mencoba ini:
sumber
find
sebenarnya jarang --printf
operator tidak ditentukan. Ini tidak berfungsi dengan BSDfind
. Jadi, tidak "sepenuhnya kompatibel POSIX." (Padahalsort -u
dalam POSIX .)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
, atauawk
jelas 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
Hapus beberapa
*f*
file daridir1/*
:Approach # 1 - Parsing via string
Di sini kita akan menggunakan alat-alat berikut,
find
,grep
, dansort
.Approach # 2 - Parsing menggunakan file
Rantai alat yang sama seperti sebelumnya, kecuali kali ini kami akan menggunakan
dirname
bukangrep
.CATATAN: Contoh di atas hanya digunakan
head -5
untuk membatasi jumlah output yang kita hadapi untuk contoh-contoh ini. Biasanya akan dihapus untuk mendapatkan daftar lengkap Anda!Membandingkan hasilnya
Kita dapat menggunakan
time
untuk melihat 2 pendekatan.dirname
grep
Jadi selalu yang terbaik untuk berurusan dengan string jika memungkinkan.
Metode penguraian string alternatif
grep & PCRE
sed
awk
sumber
Inilah yang menurut saya berguna:
sumber
Jawaban ini tanpa malu-malu didasarkan pada jawaban slm. Itu adalah pendekatan yang menarik, tetapi memiliki batasan jika nama file dan / atau direktori memiliki karakter khusus (spasi, semi-kolom ...). Kebiasaan yang baik adalah menggunakan
find /somewhere -print0 | xargs -0 someprogam
.Contoh data
Untuk contoh di bawah ini kami akan menggunakan data berikut
Hapus beberapa
*f*
file daridir1/*/
:Pendekatan # 1 - Parsing menggunakan file
CATATAN : Contoh di atas hanya digunakan
head -5
untuk membatasi jumlah output yang kita hadapi untuk contoh-contoh ini. Biasanya akan dihapus untuk mendapatkan daftar lengkap Anda! juga, gantiecho
perintah apa pun yang ingin Anda gunakan.sumber
Dengan
zsh
:sumber