Daftar subdirektori hanya dalam level n


58

Festival menyimpan data voicepack dalam struktur direktori contoh berikut:

/usr/share/festival/voices/<language>/<voicepack name>

Apa one-liner paling sederhana (lebih disukai menggunakan ls) untuk mencetak hanya <voicepack name>, di semua <language>subdirektori yang berpotensi banyak ?

Jawaban:


80

Saya menggunakan Fedora, dan paket suara ini berada di lokasi yang sedikit berbeda:

$ ls /usr/share/festival/lib/voices/*/ -1 | grep -vE "/usr|^$"
kal_diphone
ked_diphone
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_rms_arctic_hts
nitech_us_slt_arctic_hts

Anda bisa memodifikasi seperti ini:

$ ls /usr/share/festival/voices/*/ -1 | grep -vE "/usr|^$"

Menggunakan find

Penggunaan lsdi rumah ini biasanya disukai karena hasil dari lssulit untuk diurai. Lebih baik menggunakan findperintah, seperti:

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -exec basename {} \;
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_slt_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_rms_arctic_hts
ked_diphone
kal_diphone

Detail menemukan & nama kecil

Perintah ini bekerja dengan menghasilkan daftar path lengkap ke file yang tepat 2 level sehubungan dengan direktori ini:

/usr/share/festival/lib/voices

Daftar ini terlihat seperti ini:

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 
/usr/share/festival/lib/voices/us/nitech_us_awb_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_bdl_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_slt_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_jmk_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_clb_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_rms_arctic_hts
/usr/share/festival/lib/voices/english/ked_diphone
/usr/share/festival/lib/voices/english/kal_diphon

Tapi kami ingin bagian terakhir dari direktori ini, simpul daun. Jadi kita dapat menggunakan basenameuntuk menguraikannya:

$ basename /usr/share/festival/lib/voices/us/nitech_us_awb_arctic_hts
nitech_us_awb_arctic_hts

Menyatukan semuanya, kita bisa membuat findperintah melewati setiap direktori 2 level ke basenameperintah. Notasi basename {}adalah apa yang melakukan konversi nama dasar ini. Temukan panggilan melalui -execsakelar itu.


lol, jawaban yang hampir sama persis , pikiran yang hebat dan semua itu :).
terdon

+1 - Bagi mereka yang tersandung ketika mencari tahu apa yang -exec basename {}terjadi, dapatkah Anda jelaskan di sini?
user66001

@ user66001 - beri tahu saya jika itu cukup menjelaskan.
slm

@ user66001 - Anda dapat menerima salah satu jawaban jika itu menyelesaikan masalah Anda dengan kepuasan 8-)
slm

1
Perintah find adalah yang saya butuhkan 99% dari waktu. Batasi baik max dan min adalah kunci - saya hanya melakukan max. Contoh: find ~/ -maxdepth 1 -mindepth 1 -type d | xargs du -csh | sort -h Temukan direktori terbesar yang diurutkan berdasarkan ukuran
oligofren

23

Yang paling mudah adalah

ls -d /usr/share/festival/voices/*/*

Itu diperluas oleh shell ke semua sub direktori /usr/share/festival/voices/dan kemudian ke isi dari masing-masing sub direktori.

Jika Anda hanya ingin turun ke level tertentu seperti judul Anda, dengan beberapa implementasi findseperti GNU dan beberapa BSD:

find /usr/share/festival/voices/ -mindepth 2 -maxdepth 3 -type d

Itu akan menemukan semua direktori ( -type d) yang ada di subdirektori /usr/share/festival/voices/karena mindepth 2tetapi tidak lebih dalam dari 3 level ke bawah ( maxdepth 3). Dari man find:

   -maxdepth levels
          Descend at most levels (a non-negative integer) levels of direc
          tories below the command line arguments.  -maxdepth 0
           means only apply the tests and  actions  to  the  command  line
          arguments.

   -mindepth levels
          Do  not apply any tests or actions at levels less than levels (a
          non-negative integer).  -mindepth  1  means  process  all  files
          except the command line arguments.

Ya itu seperti melihat di cermin 8-)
slm

+1 Bagaimana Anda berdua mendapat 2 suara menarik. Lintas voting menjelaskan 1 masing-masing;) PS saya ingin nama direktori, jadi hanya mengubah -type fke -type dharus mengatasi ini, kan? Akan juga menunggu tanggapan slm mengenai tujuan-exec basename {}
user66001

@ user66001 ya, -type dakan menemukan direktori. Ini basenameadalah ide yang sangat bagus, itu hanya akan mencetak nama dan menghapus path. Dengan asumsi Anda hanya menginginkan nama, itulah yang harus Anda lakukan. Lihat man basenamedan juga man dirname.
terdon

Terima kasih terdon - Maaf karena tidak menandai jawaban Anda. Merasa bahwa versi saat ini slm 's memiliki informasi lebih lanjut, bagi mereka yang membutuhkannya.
user66001

1
@ user66001 pertama-tama, Anda memang benar, slm memang lebih baik. Kedua Anda seharusnya tidak pernah meminta maaf karena tidak menerima, hanya ada satu dan itu yang harus Anda anggap terbaik :).
terdon

6

The jawaban diterima bekerja dengan benar tapi agak tidak efisien karena memunculkan baru basenameproses untuk setiap subdirektori:

find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -exec basename {} \;

Jika memungkinkan, lebih baik menggunakan fitur yang dibangun finduntuk menghindari biaya proses pemijahan. findmemiliki kemampuan yang cukup luas untuk memodifikasi hasil cetaknya menggunakan -printfaction. Tindakan default -print mencetak seluruh jalur, tetapi menggunakan -printfdan format string mungkin untuk memilih bagian dari jalur untuk dicetak. Untuk mengekstrak hanya bagian nama file dari path tanpa direktori utama (seperti basename halnya), format string adalah %f. Untuk menempatkan baris baru setelah setiap nama file, sertakan \nsebagai berikut:

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -printf '%f\n'
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_slt_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_rms_arctic_hts
ked_diphone
kal_diphone

+1 Terima kasih atas jawaban Anda Michael. Saya dapat melihat keuntungan dari cara melakukan ini dalam jawaban Anda, juga, tetapi mengingat pekerjaan ini dimasukkan ke dalam jawaban slm, saya ragu untuk mengalihkan jawaban yang diterima. Jika @slm melihat ini, dan tidak memiliki masalah dengan memilih ini daripada miliknya, saya akan kembali ke sini untuk mengubah jawaban yang diterima.
user66001

1
Jawaban @ slm dijelaskan dengan baik dan mencakup pola penggunaan yang lebih umum finddengan perintah eksternal yang arbitrer; itu hanya kurang efisien untuk operasi yang dibangun find. Saya telah mempertimbangkan untuk menambahkan komentar pada jawabannya, tetapi itu membutuhkan lebih banyak reputasi daripada yang saya miliki. Tidak perlu mengubah jawaban yang Anda terima, karena jawaban yang diterima saat ini benar, dijelaskan dengan baik, dan dapat digunakan sebagai pola untuk kasus yang lebih umum; Saya hanya ingin menunjukkan bahwa untuk kasus khusus ini ada metode yang lebih efisien.
Michael Henry

0

TLDR; untuk mereka yang datang ke sini berdasarkan judul pertanyaan ini; untuk "Daftar subdirektori hanya dalam n level": gunakan

find -maxdepth N

di mana Nada nomor

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.