Temukan daftar direktori sedalam satu tingkat dari direktori yang cocok

13

Saya mencoba untuk mendapatkan daftar direktori yang terkandung dalam folder tertentu.

Diberikan folder contoh ini:

foo/bar/test
foo/bar/test/css
foo/bar/wp-content/plugins/XYZ
foo/bar/wp-content/plugins/XYZ/js
foo/bar/wp-content/plugins/XYZ/css
baz/wp-content/plugins/ABC
baz/wp-content/plugins/ABC/inc
baz/wp-content/plugins/ABC/inc/lib
baz/wp-content/plugins/DEF
bat/bar/foo/blog/wp-content/plugins/GHI

Saya ingin perintah yang akan kembali:

XYZ
ABC
DEF
GHI

Pada dasarnya, saya mencari folder yang ada di dalam wp-content / plugins /

Menggunakan findtelah membuat saya paling dekat, tetapi saya tidak dapat menggunakan -maxdepth, karena folder itu sangat jauh dari tempat saya mencari.

Menjalankan berikut ini mengembalikan semua direktori anak, secara rekursif.

find -type d -path *wp-content/plugins/*

foo/bar/wp-content/plugins/XYZ
foo/bar/wp-content/plugins/XYZ/js
foo/bar/wp-content/plugins/XYZ/css
baz/wp-content/plugins/ABC
baz/wp-content/plugins/ABC/inc
baz/wp-content/plugins/ABC/inc/lib
baz/wp-content/plugins/DEF
bat/bar/foo/blog/wp-content/plugins/GHI
Nick
sumber

Jawaban:

14

Cukup tambahkan -prunesehingga direktori yang ditemukan tidak turun ke:

find . -type d -path '*/wp-content/plugins/*' -prune -print

Anda perlu mengutip bahwa *wp-content/plugins/*itu juga shell glob.

Jika Anda hanya menginginkan nama direktori yang bertentangan dengan path lengkapnya, dengan GNU find, Anda dapat mengganti -printdengan -printf '%f\n'atau dengan asumsi path file tidak mengandung karakter baris baru, menyalurkan output dari perintah di atas ke awk -F / '{print $NF}'atau sed 's|.*/||'(juga dengan asumsi path file mengandung hanya karakter yang valid).

Dengan zsh:

printf '%s\n' **/wp-content/plugins/*(D/:t)

**/adalah setiap tingkat subdirektori (fitur yang berasal zshdi nighties awal, dan sekarang ditemukan di sebagian besar kerang lainnya suka ksh93, tcsh, fish, bash, yashmeskipun umumnya di bawah beberapa opsi), (/)untuk memilih hanya file jenis direktori , Duntuk memasukkan tersembunyi (dot) yang, :tuntuk dapatkan ekornya (nama file).

Stéphane Chazelas
sumber
Temuan ini akan mengonversi baris baru dalam direktori menjadi ?. Untuk bash, (seperti yang ditandai pada pertanyaan) ini berfungsi .
Isaac
@sorontar, findimplementasi yang menghasilkan ?karakter pengganti atau apa pun atau segala bentuk pelarian untuk karakter yang tidak dapat dicetak hanya melakukan hal itu ketika output pergi ke terminal, bukan ketika pergi ke pipa seperti di sini.
Stéphane Chazelas
Perintah pertama (dan hanya non zsh) yang ada di jawaban Anda tidak memiliki pipa, itu yang saya uji, dan yang mengubah baris baru. Ketika disalurkan, seperti yang Anda katakan: "dengan asumsi jalur file tidak mengandung karakter baris baru", jadi, Anda sudah mengakui bahwa jalur itu juga gagal dengan baris baru.
Isaac
@sorontar, maaf saya pikir Anda mengomentari bagian kedua untuk mengatakan bahwa itu akan bekerja dengan baik karena baris baru akan lolos sehingga tidak akan melanggar asumsi yang kami buat untuk sed/ awkbahwa semua file berada pada satu baris. Sekarang, Seseorang mungkin berpendapat bahwa mendapatkan ABC?BCDatau ABC\nBCDuntuk output interaktif / terminal akan lebih berguna daripada mendapatkan dua ABCdan BCDbaris untuk dir disebut $'ABC\nBCD. Itu pada tingkat presentasi pengguna, kami juga dapat menunjukkan bahwa untuk file bernama $'AB\bC', ketika output masuk ke terminal, Anda akan melihat ACtanpa ?penggantian seperti itu ...
Stéphane Chazelas
Temukan dengan -prune dan menggunakan printf untuk mengubah format output memberi saya apa yang saya minta. Sempurna - terima kasih!
Nick
4

Bash-ically:

shopt -s globstar
printf "%s\n" **/wp-content/plugins/*

cetakan:

bat/bar/foo/blog/wp-content/plugins/GHI
baz/wp-content/plugins/ABC
baz/wp-content/plugins/DEF
foo/bar/wp-content/plugins/XYZ

atau

shopt -s globstar
for d in **/wp-content/plugins/*; do printf "%s\n" ${d##*/}; done

cetakan:

GHI
ABC
DEF
XYZ
Jeff Schaller
sumber
Tidak, itu akan mencetak file di dalam dir juga. Tolong baca jawaban saya.
Isaac
Poin bagus; Terima kasih! Saya telah menciptakan kembali struktur direktori mereka, tetapi tidak menempatkan file tes di dalamnya.
Jeff Schaller
4

Anda bisa memiliki findpengulangan, semacam:

find / -type d -path *wp-content/plugins -exec find {} -maxdepth 1 -mindepth 1 -type d \;
DopeGhoti
sumber
3

Untuk Bash: Sederhana (berfungsi untuk file / dir dengan spasi dan baris baru ):

shopt -s globstar                    # allow ** for several dirs.
a=(**/wp-content/plugins/*/)         # capture only wanted dirs.
a=("${a[@]%/}")                      # remove trailing slash (dirs) `/`.
printf '%s\n' "${a[@]##*/}"          # print only the last dir name.

Akan dicetak:

GHI
ABC
DEF
XYZ

Bahkan jika ada file yang dibuat.

Ishak
sumber
Perhatikan bahwa ia tidak melihat ke dalam dirs tersembunyi, melompati file tersembunyi (lihat dotglobopsi jika itu tidak diinginkan) dan menyertakan symlink ke direktori selain direktori ( **juga akan melintasi symlink di bash 4.2 dan sebelumnya).
Stéphane Chazelas
@ StéphaneChazelas file tersembunyi? Pertanyaannya tidak meminta, hanya dir. Ya, dirs tersembunyi dapat dipilih secara independen (sebagai fitur, jika diinginkan). Dan ya, symlink tidak melintang di versi bash saat ini.
Isaac
1
tolong jangan anggap komentar saya sebagai agresi. Saya membatalkan jawaban Anda dan menambahkan catatan di bawah untuk menunjukkan beberapa fakta tentang hal itu yang belum tentu jelas. findtidak mengecualikan file apa pun. gumpalan tidak termasuk file dot, ada baiknya menunjukkan sebagai perbedaan antara keduanya.
Stéphane Chazelas
3

The treeperintah dirancang tepat untuk tujuan ini. Kedalaman dapat dikontrol dengan -Lbendera. Berikut adalah contoh di situs Wordpress lokal yang saya kelola:

$ tree -L 1 wp-content/
wp-content/
├── index.php
├── plugins
└── themes

2 directories, 1 file

$ tree -L 2 wp-content/
wp-content/
├── index.php
├── plugins
   ├── akismet
   ├── contact-form-7
   ├── index.php
   └── wordpress-seo
└── themes
    ├── index.php
    ├── twentyfifteen
    └── twentysixteen

11 directories, 3 files

$ tree -L 1 wp-content/plugins/
wp-content/plugins/
├── akismet
├── contact-form-7
├── index.php
└── wordpress-seo

5 directories, 1 file
dotancohen
sumber
1

Membangun dari jawaban DopeGhoti, bagaimana dengan lingkaran pencocokan:

find / -type d -iregex '.*/wp-content/plugins' -print0 | while read -r -d $'\0' D; do
    find "$D" -maxdepth 2 -mindepth 1
done

Alasan untuk melakukannya dengan cara ini adalah bahwa Anda mungkin merasa membingungkan / rumit dengan banyak -exec, sementara masih menghindari masalah dengan nama file aneh yang mengandung \ n '', dll. -Print0 akan menggunakan pemisah nol antara hasil.

Ed Neville
sumber
0

Membangun apa yang Anda mulai:

find -type d -path *wp-content/plugins/* | egrep -o "wp-content/plugins/[^/]+($|/)" | sed -r "s~wp-content/plugins/([^/]+)($|/)~\1~" | uniq  

egrep meraih * wp-content / plugins / * dan setiap karakter hingga $ / akhir baris berikutnya - yang termasuk bagian yang Anda inginkan.

sed , dengan ~ pembatas, memilih bagian yang Anda inginkan menggunakan set kurung pertama () dan menggunakan \ 1 (apa yang Anda inginkan) sebagai pengganti segalanya

uniq memfilter hasil duplikat

MikeD
sumber