2012-06-22 36 views
7

Tôi có một cấu trúc tập tin đó trông như thế nàyLàm cách nào để tìm tệp trong mỗi thư mục có số lượng tệp cao nhất?

./501.res/1.bin 
./503.res/1.bin 
./503.res/2.bin 
./504.res/1.bin 

và tôi muốn tìm ra đường dẫn tập tin vào .bin tập tin trong mỗi thư mục có số lượng cao nhất như tên tập tin. Vì vậy, sản lượng Tôi đang tìm kiếm sẽ

./501.res/1.bin 
./503.res/2.bin 
./504.res/1.bin 

Số cao nhất một tập tin có thể có được 9.

Câu hỏi

Làm thế nào để làm điều đó trong BASH?

tôi đã đi xa như find .|grep bin|sort

Trả lời

1

gì về sử dụng awk? Bạn có thể nhận được sự xuất hiện đầu tiên thực sự đơn giản:

[[email protected] ~]$ cat data1 
./501.res/1.bin 
./503.res/1.bin 
./503.res/2.bin 
./504.res/1.bin 
[[email protected] ~]$ awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' data1 
./501.res/1.bin 
./503.res/1.bin 
./504.res/1.bin 
[[email protected] ~]$ 

Để có được sự xuất hiện cuối cùng bạn có thể đường ống thông qua một vài loại:

[[email protected] ~]$ sort -r data1 | awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' | sort 
./501.res/1.bin 
./503.res/2.bin 
./504.res/1.bin 
[[email protected] ~]$ 

Cho rằng bạn đang sử dụng "tìm" và "grep" , bạn có thể có thể làm điều này:

find . -name \*.bin -type f -print | sort -r | awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' | sort 

Cách thức hoạt động?

Lệnh find có nhiều tùy chọn hữu ích, bao gồm khả năng chọn tệp của bạn theo glob, chọn loại tệp, v.v ... đầu ra của nó mà bạn đã biết và trở thành đầu vào là sort -r.

Đầu tiên, chúng tôi sắp xếp dữ liệu đầu vào của chúng tôi ngược lại (sort -r). Điều này đảm bảo rằng trong bất kỳ thư mục nào, tệp được đánh số cao nhất sẽ hiển thị trước tiên. Kết quả đó được cho ăn vào vụng về. FS là bộ tách trường, làm cho $2 thành những thứ như "/ 501", "/ 502", v.v. Các tập lệnh Awk có các phần ở dạng condition {action} được đánh giá cho từng dòng đầu vào. Nếu một điều kiện bị thiếu, hành động sẽ chạy trên mọi dòng. Nếu "1" là điều kiện và không có hành động, nó sẽ in ra dòng. Vì vậy, kịch bản này được chia ra như sau:

  • a[$2] {next} - Nếu mảng a với chỉ số dưới $ 2 (tức là "/ 501") tồn tại, chỉ cần nhảy tới dòng tiếp theo. Nếu không ...
  • {a[$2]=1} - đặt mảng thành chỉ số $ 2 đến 1, để trong tương lai điều kiện đầu tiên sẽ đánh giá là đúng, thì ...
  • 1 - in dòng.

Đầu ra của tập lệnh awk này sẽ là dữ liệu bạn muốn, nhưng theo thứ tự ngược lại. Cuối cùng sort đặt mọi thứ trở lại theo thứ tự bạn mong đợi.

Bây giờ ... đó là rất nhiều ống, và sắp xếp có thể là một chút tài nguyên đói khi bạn yêu cầu nó để đối phó với hàng triệu dòng đầu vào cùng một lúc. Giải pháp này sẽ hoàn toàn đủ cho số lượng tệp nhỏ, nhưng nếu bạn đang xử lý số lượng lớn dữ liệu đầu vào, hãy cho chúng tôi biết và tôi có thể đưa ra giải pháp tất cả trong một (sẽ mất hơn 60 giây) viết).

CẬP NHẬT

lời khuyên khôn

mỗi Dennis', kịch bản awk tôi bao gồm ở trên có thể được cải thiện bằng cách thay đổi nó từ

BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1 

để

BEGIN{FS="."} $2 in a {next} {a[$2]} 1 

Trong khi điều này có chức năng giống hệt nhau , lợi thế là bạn chỉ cần định nghĩa các thành viên mảng thay vì gán các giá trị cho chúng, điều này có thể tiết kiệm bộ nhớ hoặc cpu de đang chờ bạn triển khai awk. Ở mức nào, nó sạch hơn.

+0

Tốt hơn là kiểm tra sự tồn tại của một phần tử trong một mảng bằng cách sử dụng '$ 2 trong một {next}'. Làm theo cách đó không tạo ra các phần tử mảng mới chỉ đơn giản bằng cách tham chiếu đến chúng. Đây là những gì tôi muốn nói ngày hôm kia khi chúng tôi thảo luận về điều này. Bằng cách này, nếu bạn sử dụng 'in' theo cách đó, bạn có thể làm' {a [$ 2]} 'thay vì' {a [$ 2] = 1} ', nhưng sẽ hoạt động. –

+0

@DennisWilliamson, AH, bây giờ tôi hiểu những gì bạn đã nhận được vào ngày khác. Cảm ơn rất nhiều cho con trỏ. :) – ghoti

0

tôi đến với someting như thế này:

for dir in $(find . -mindepth 1 -type d | sort); do 
    file=$(ls "$dir" | sort | tail -n 1); 
    [ -n "$file" ] && (echo "$dir/$file"); 
done 

Có lẽ nó có thể được đơn giản

+0

Tôi nghĩ bạn nên có loại -n như việc đánh số có thể đi cao hơn 9. – bcelary

+0

@bcelary - OP nói * "Số lượng cao nhất mà một tập thể có là 9. "* – ghoti

+0

Ah - xin lỗi. Không thể thông báo :) – bcelary

2

Tested:

find . -type d -name '*.res' | while read dir; do 
    find "$dir" -maxdepth 1 | sort -n | tail -n 1 
done 
+1

Nó không hiển thị đường dẫn. – jcubic

+0

Đã sửa lỗi. tìm ... -maxdepth 1 hiển thị đường dẫn chính xác ngay bây giờ. Cảm ơn. – bcelary

0

Nếu gọi một vỏ từ bên trong tìm là một lựa chọn thử này

find * -type d -exec sh -c "echo -n './'; ls -1 {}/*.bin | sort -n -r | head -n 1" \; 
3

globs được đảm bảo để được mở rộng theo thứ tự từ vựng.

for dir in ./*/ 
do 
    files=($dir/*)   # create an array 
    echo "${files[@]: -1}" # access its last member 
done 
0

Và đây là một trong lót

find . -mindepth 1 -type d | sort | sed -e "s/.*/ls & | sort | tail -n 1 | xargs -I{} echo &\/{}/" | bash 
Các vấn đề liên quan