Loại trừ các thư mục trong tìm kiếm định vị


12

Một tìm kiếm với locatecác đường dẫn trong hệ thống tập tin.
Thông thường, bạn biết một tiên nghiệm mà bạn quan tâm chỉ trong các tệp hoặc chỉ thư mục.
Tìm kiếm 'định vị' thường trả về nhiều kết quả. Sẽ rất hữu ích khi chỉ bao gồm một trong các loại trong kết quả, vì nó giúp rút ngắn đầu ra.

Nhưng có một đối số thú vị hơn để loại bỏ các tệp hoặc thư mục: bởi vì danh sách các đường dẫn kết quả có thể không rõ ràng - không chỉ trong lý thuyết.

Ví dụ dưới đây là trường hợp thực tế và không bất thường:

$ locate --regex --basename "xfce4-keyboard-overlay$"
/usr/local/bin/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay

Ok, chúng tôi đã tìm thấy một cái gì đó! Nhưng ... tập tin, hay thư mục?

$ file /usr/local/bin/xfce4-keyboard-overlay 
/usr/local/bin/xfce4-keyboard-overlay:   bash script

Vậy đó là một tập tin ...

$ file /usr/local/share/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay: directory

trong khi thứ hai thì không.

Sự không rõ ràng này đang làm cho danh sách dài các đường dẫn khó đọc, vì vậy sẽ rất tốt để lọc các thư mục, ví dụ như sử dụng tùy chọn dòng comman cho locate.

Có một cái gì đó như thế này tồn tại? Ngay cả khi bộ lọc cho các thư mục là tách biệt với định vị?

Ít nhất, người ta có thể sử dụng một tập lệnh để lặp lại tất cả các tên tệp để kiểm tra - có thể bị chậm.

Câu trả lời:


3

Với zsh:

print -rl ${(0)^"$(locate -0 ...)"}(N.)

(0)là cờ mở rộng tham số phân tách trên các ký tự NUL (như chúng ta sử dụng locate -0), viết tắt của (ps:\0:).

Với ^, thay vì thêm (N.)vào cuối mảng, chúng tôi thêm nó vào từng phần tử.

(N.)là một vòng loại toàn cầu, .chỉ khớp với các tệp thông thường, Nđể loại bỏ phần tử nếu nó không khớp (không tồn tại hoặc không phải là tệp thông thường hoặc chúng tôi không thể kiểm tra). Bạn cũng có thể sử dụng ^/thay vì .khớp với các thư mục không thay vì chỉ các tệp thông thường.

print -rlin từng đối số thô trên một dòng riêng biệt .

Bạn có thể sử dụng bất kỳ zshvòng loại toàn cầu nào , nhưng lưu ý rằng những người đặt hàng sẽ không có bất kỳ ảnh hưởng nào, vì chúng tôi đang mở rộng một quả địa cầu cho mỗi tệp ở đây, vì vậy chỉ có một tệp để sắp xếp cho mỗi tệp.

(lưu ý rằng nó có thể thất bại nếu tệp cuối cùng được báo cáo locatekết thúc bằng các ký tự dòng mới (một lỗi sai thay thế lệnh có trong tất cả các shell)).


3

Đây là về không phù hợp như các câu trả lời khác, nhưng có thể ít hiệu quả hơn:

locate --regex --basename "xfce4-keyboard-overlay$" | 
        while IFS= read -r f; do [ -f "$f" ] && printf "%s\n" "$f"; done

(chia thành hai dòng để dễ đọc). Ở trên sẽ xử lý tên chứa không gian. Các IFS=có vẻ là cần thiết để xử lý tên với đuôi không gian, và, tất nhiên, -rcho phép bạn xử lý những dấu xồ nguợc.

Đường ống của Let Let locatevào một cái gì đó Cách tiếp cận có thể bị thất bại nếu có tên đường dẫn chứa dòng mới.


Để biết thêm thông tin về IFS, hãy đọc sh(1)hoặc bash(1) (bằng cách nhập man shhoặc man bashvào hệ thống * nix và / hoặc đọc nó ở đây , ở đây , ở đây và / hoặc ở đây ). Sau đó đọc Hiểu IFSBash: đọc từng dòng, với IFS trên Stack Exchange (tập trung vào các câu trả lời có hơn 5 phiếu) và, nếu bạn vẫn chưa có đủ, hãy xem IFS trên kết quả tìm kiếm WikiIFS của Greg trên Bash Hackers Wiki (không phải trên Stack Exchange).


bạn có thể thêm một số thông tin về "IFS =" sau whilecâu lệnh của bạn không?
robert

Tôi đã làm như vậy.
G-Man nói 'Phục hồi Monica'

dấu gạch chéo ngược vẫn sẽ là một vấn đề với nhiều triển khai echo. Bạn nên sử dụng printfcho dữ liệu tùy ý .
Stéphane Chazelas

có thể có một giải pháp cho vấn đề về dòng mới của bạn bằng cách sử dụng tham số "--null" để locategia tăng readnhư bạn đã đề xuất ở đây transnum.blogspot.ie/2008/11/ trên
robert

@ StéphaneChazelas: Điểm tốt. Đã sửa.
G-Man nói 'Tái lập lại' '

2
locate --null --regex --basename "xfce4-keyboard-overlay$" |
  xargs -r0 sh -c 'find "$@" -prune ! -type d' sh

Trên thực tế, nó thậm chí còn bẩn hơn vẻ ngoài của nó ... nhưng là một nguồn cảm hứng tốt. Hãy giả vờ đó là mã giả, sau đó nó hữu ích :)
Volker Siegel

1
@Volker: Tôi đồng ý rằng điều đó thật tệ: nó sẽ liệt kê /usr/local/share/xfce4-keyboard-overlay và mọi thư mục con của chúng , trong ví dụ của bạn. Thêm -maxdepth 0trợ giúp.
G-Man nói 'Phục hồi Monica'

Nó thậm chí còn tốt hơn ...: D locate --regex --basename "xfce4-keyboard-overlay$" | xargs -I % sh -c "test -d % && echo %"
FloHimelf

1
Sử dụng xargsvới findlà một ý tưởng tốt, tôi đã chỉnh sửa nó để làm cho nó mạnh mẽ. Hy vọng bạn không phiền.
Stéphane Chazelas

1

xargssẽ lặp lại lệnh cho mỗi dòng nếu bạn chỉ định -L 1hoặc -itham số.

Xem tại đây

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i bash -c '(test -d "{}" && echo "{}")'

Phải thừa nhận rằng, nó đang khởi động một lớp vỏ mới cho mỗi tệp, nhưng nó có lợi ích là đẹp và gọn.

EDIT: Tôi không hài lòng lắm với câu trả lời đó vì nó đã tạo ra một lớp vỏ mới cho mỗi tệp. Điều này chỉ nên có hai quá trình:

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i echo 'test -d "{}" && echo "{}"' | bash

Tất nhiên sẽ rất tuyệt nếu chúng ta có thể tránh việc đá một người phiên dịch hoàn toàn, nhưng xargsdường như bị cản trở trong khả năng xâu chuỗi các lệnh của nó.


3
Cái đó vừa khởi động lại máy của tôi (có một tệp được gọi /home/evil/$(reboot)/xfce4-keyboard-overlayvà tôi dại dột chạy nó như root).
Stéphane Chazelas

2
@ StéphaneChazelas +1 vì sự can đảm để chạy "codez ngẫu nhiên từ các mạng nội bộ" với quyền root;) (scnr)
Volker Siegel

0

Theo quan điểm của tôi:

while IFS= read i; \
do \
  if [ -f "$i" ]; \
  then \
    echo "$i"; \
  fi; \
done < <(locate --regex --basename "xfce4-keyboard-overlay$")

Đây ít nhiều là cách mà G-Man đã làm nó kết hợp với quá trình thay thế.


Trên thực tế, đây ít nhiều là cách tôi đã làm, kết hợp với thay thế quy trình, trừ khả năng xử lý tên tệp có dấu gạch chéo ngược hoặc có khoảng trắng ở cuối. Ngoài ra, lưu ý rằng tiêu đề câu hỏi cho biết "loại trừ các thư mục" và câu trả lời này chỉ bao gồm các thư mục.
G-Man nói 'Phục hồi Monica'

Lấy làm tiếc. Lỗi của tôi. Đã sửa.
Tristan Storch

-1

Điều gì nếu bạn kết hợp locatevới filegrep? ...

$ for f in `locate --regex --basename "xfce4-keyboard-overlay$"`; do file $f; done | grep -vi directory

Tôi đã không kiểm tra, nhưng tôi nghĩ rằng điều đó có thể chậm, bởi vì nó tạo ra một quy trình filecho mỗi con đường. Lưu ý rằng thường có nhiều dòng kết quả để xác định vị trí. Bài kiểm tra hiện tại của tôi đang tìm kiếm "gnome", đưa ra khoảng 73000 đường dẫn để kiểm tra.
Volker Siegel

2
@Volker: Tệ hơn thế: cho mọi $f tệp là một filechương trình, chương trình sẽ mở tệp đó và đọc từ đó . Điều này là rất tốn kém khi tất cả những gì bạn cần làm là a stat(). Ngoài ra, phần mềm này sẽ cung cấp kết quả sai cho các tệp có chứa "thư mục" trong tên của họ (chẳng hạn như "phone_directory"). ... ... ... ... ... (Ngoài ra, for f in `…`; do …cú pháp có thể không xử lý tên có chứa dấu cách.)
G-Man Says 'Khôi phục Monica'
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.