Về cơ bản có 2 phương pháp bạn có thể sử dụng để làm điều này. Một cái sẽ phân tích chuỗi trong khi cái còn lại sẽ hoạt động trên mỗi tệp. Phân tích chuỗi sử dụng một công cụ như grep
, sed
hoặc awk
là rõ ràng là sẽ nhanh hơn nhưng đây là một ví dụ cho thấy cả hai, cũng như làm thế nào bạn có thể "hồ sơ" 2 phương pháp.
Dữ liệu mẫu
Đối với các ví dụ dưới đây, chúng tôi sẽ sử dụng dữ liệu sau
$ touch dir{1..3}/dir{100..112}/file{1..5}
$ touch dir{1..3}/dir{100..112}/nile{1..5}
$ touch dir{1..3}/dir{100..112}/knife{1..5}
Xóa một số *f*
tệp khỏi dir1/*
:
$ rm dir1/dir10{0..2}/*f*
Cách tiếp cận số 1 - Phân tích cú pháp qua chuỗi
Dưới đây chúng ta sẽ sử dụng các công cụ sau, find
, grep
, và sort
.
$ find . -type f -name '*f*' | grep -o "\(.*\)/" | sort -u | head -5
./dir1/dir103/
./dir1/dir104/
./dir1/dir105/
./dir1/dir106/
./dir1/dir107/
Cách tiếp cận # 2 - Phân tích cú pháp bằng các tệp
Cùng một chuỗi công cụ như trước đây, ngoại trừ lần này chúng ta sẽ sử dụng dirname
thay vì grep
.
$ find . -type f -name '*f*' -exec dirname {} \; | sort -u | head -5
./dir1/dir103
./dir1/dir104
./dir1/dir105
./dir1/dir106
./dir1/dir107
LƯU Ý: Các ví dụ trên đang sử dụng head -5
để chỉ giới hạn số lượng đầu ra mà chúng tôi đang xử lý cho các ví dụ này. Họ thường sẽ bị xóa để có được danh sách đầy đủ của bạn!
So sánh kết quả
Chúng ta có thể sử dụng time
để xem xét 2 cách tiếp cận.
tên hiệu
real 0m0.372s
user 0m0.028s
sys 0m0.106s
grep
real 0m0.012s
user 0m0.009s
sys 0m0.007s
Vì vậy, tốt nhất là luôn luôn xử lý các chuỗi nếu có thể.
Các phương pháp phân tích chuỗi thay thế
grep & PCRE
$ find . -type f -name '*f*' | grep -oP '^.*(?=/)' | sort -u
quyến rũ
$ find . -type f -name '*f*' | sed 's#/[^/]*$##' | sort -u
ôi
$ find . -type f -name '*f*' | awk -F'/[^/]*$' '{print $1}' | sort -u
uniq
vào hỗn hợp giúp rất nhiều bằng cách loại bỏ các dòng lặp đi lặp lại ngay cạnh nhau.find . -type f -name '*f*' -printf '%h\0' | uniq -z | sort -zu | tr '\0' '\n'
. Hoặc nếu công cụ của bạn cũ hơn một chút, thì uniq có thể không có tùy chọn -z.find . -type f -name '*f*' -printf '%h\n' | uniq | sort -u