Không bao gồm tên thư mục trong thế giới đệ quy zsh


7

Tôi đang chạy zsh trên Linux setopt extended_glob ksh_glob glob_dots. Tôi đang tìm kiếm một cái gì đó dễ dàng để gõ trên dòng lệnh, không có yêu cầu về tính di động. Tôi đang xem một cây mã nguồn, không có tên tập tin kỳ lạ của người Viking (ví dụ: không có \tên tệp, không có tên tệp bắt đầu bằng -).

Một trong các lệnh sau sẽ in danh sách các thư mục con của thư mục hiện tại theo cách đệ quy:

find -type d
print -l **/*/

Đây thực sự là một kiểm tra svn:

$ find -type d
./.deps
./.svn
./.svn/text-base
./.svn/prop-base
./.svn/tmp
./.svn/tmp/text-base
./.svn/tmp/prop-base
./.svn/tmp/props
./.svn/props
./lib/.svn
./lib/.svn/text-base
./lib/.svn/prop-base
./lib/.svn/tmp
./lib/.svn/tmp/text-base
./lib/.svn/tmp/prop-base
./lib/.svn/tmp/props
./src/.svn
./src/.svn/text-base
./src/.svn/prop-base
./src/.svn/tmp
./src/.svn/tmp/text-base
./src/.svn/tmp/prop-base
./src/.svn/tmp/props

Tôi muốn loại trừ các .svnthư mục và thư mục con của chúng có trong mọi thư mục. Thật dễ dàng với find:

find -type d -name .svn -prune -o -print

Tôi có thể làm điều này với một zsh toàn cầu ngắn? Bỏ qua các tệp chấm đến gần (tôi cần làm rõ ràng vì tôi đã glob_dotsđặt):

print -l **/*(/^D)

Nhưng điều này không thỏa đáng vì nó ẩn .depsthư mục mà tôi muốn xem. Tôi có thể lọc ra các đường dẫn chứa .svn:

print -l **/*~(*/|).svn(|/*)(/)

Nhưng nó chỉ ngắn hơn find(vì vậy tôi đang sử dụng zsh để làm gì?). Tôi có thể rút ngắn nó xuống print -l **/*~*.svn*(/), nhưng nó cũng lọc ra các thư mục được gọi hello.svn. Hơn nữa, zsh đi qua các .svnthư mục, một chút chậm trên NFS hoặc Cygwin.

Có cách nào thuận tiện (như dễ gõ) để loại trừ một tên thư mục cụ thể (hoặc thậm chí tốt hơn: một mẫu tùy ý) trong một thế giới đệ quy không?


Tại sao bạn lại dành thời gian để tìm hiểu xem các tệp của bạn có hoặc không có dấu gạch ngang hoặc dấu gạch chéo ngược (và để người đọc khác tự tìm hiểu khi họ không thể đảm bảo điều đó) thay vì chỉ viết đúng thứ chống đạn như printf '%s\n' **/*hay print -rl -- **/*?
Stéphane Chazelas

@StephaneChazelas Trong một kịch bản, chắc chắn. Nhưng trên dòng lệnh, lưu 4 ký tự là xứng đáng. Trong tình huống thực tế của tôi, tôi không cần tìm hiểu về tên tệp, tôi đã biết (xây dựng cây có xu hướng có tên tệp thuần hóa).
Gilles 'SO- ngừng trở nên xấu xa'

Câu trả lời:


20

Các nhà khai thác toàn cầu mở rộng của Zsh hỗ trợ đối sánh /(không giống như ksh, ngay cả khi triển khai zsh). Zsh's **/là một phím tắt cho (*/)#( */lặp lại 0 lần trở lên). Vì vậy, tất cả những gì tôi cần làm là thay thế nó *bằng ^.svn(bất cứ điều gì nhưng .svn).

print -l (^.svn/)#

Khéo léo!


4
Đây là một câu trả lời tuyệt vời - mặc dù nó đòi hỏi setopt EXTENDED_GLOB. Không có nó, bạn sẽ nhận được zsh: bad pattern: [...].
Andy Fowler

Tôi gặp khó khăn khi áp dụng câu trả lời của bạn cho trường hợp sử dụng của tôi. Tôi đang cố gắng khớp tập hợp các CMakeLists.txttệp nằm rải rác trong nhiều thư mục con khác nhau, ngoại trừ tất cả các thư mục bắt đầu cmake-*được tìm kiếm. Tôi đã thử (^cmake-*)**/CMakeLists.txt#; nó hoạt động, nhưng nó không bao gồm CMakeLists.txttrong thư mục làm việc của tôi (tức là nó tìm thấy những nằm trong thư mục con riêng ). Làm thế nào tôi có thể bao gồm nó? Cảm ơn, và câu trả lời tuyệt vời!
brainplot

@brainplot Nếu bạn muốn loại trừ cmake-*ở mọi cấp độ, thì như trong câu trả lời của tôi, hãy sử dụng (^cmake-*/)#CMakeLists.txt. Nếu bạn chỉ muốn loại trừ cmake-foo/bar/CMakeLists.txtnhưng không baz/cmake-qux/CMakeLists.txt, bạn cần một cách tiếp cận khác : **/CMakeLists.txt~cmake-*/*.
Gilles 'SO- ngừng trở thành ác quỷ'

@Gilles tất cả các cmake-*thư mục tôi muốn loại trừ đều nằm trong thư mục hiện tại của tôi và tôi muốn loại trừ tất cả các thư mục. Tôi đã thử giải pháp đầu tiên của bạn và nó đã làm việc. Cảm ơn bạn!
brainplot

2

Mặc dù ksh93Globing không ở đâu gần zshngay cả với globstartùy chọn ksh93, nhưng có thể đạt được bằng:

set -o globstar
FIGNORE='@(.|..|.svn)'
printf '%s\n' **/
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.