Làm cách nào tôi có thể xem dòng thứ 17 (hoặc cuối cùng, nếu ít hơn) trong các tệp của một thư mục?


8

Tôi hiện đang sử dụng

watch head -n 17 *

hoạt động, nhưng cũng hiển thị tất cả các dòng đến ngày 17. Về cơ bản, tôi muốn chỉ hiển thị dòng cuối cùng cho mỗi tệp được hiển thị với phương pháp hiện tại của tôi. Làm thế nào tôi có thể đạt được điều đó?

Thí dụ

Vì lợi ích của ví dụ, hãy giảm dòng nr. đến 7. Vì vậy:

Tệp ví dụ:

1
2
3
4
5
6
7
8

đường thẳng này:

watch head -n 7 *

đầu ra

1
2
3
4
5
6
7

nơi tôi muốn:

7

Câu trả lời:


15

Với GNU awk:

watch -x gawk '
  FNR == 17 {nextfile}
  ENDFILE   {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}' ./*

Cung cấp một đầu ra như:

        ./file1[17] line17
  ./short-file2[05] line 5 is the last

Lưu ý rằng toàn ./*cầu chỉ được mở rộng một lần tại thời điểm watchđược gọi.

Your watch head -n 17 *là một lỗ hổng tiêm lệnh tùy ý vì sự mở rộng của nó *thực sự được hiểu là mã shell bởi shell mà watchgọi để giải thích sự kết hợp các đối số của nó với khoảng trắng.

Nếu có một tệp được gọi $(reboot)trong thư mục hiện tại, nó sẽ khởi động lại.

Với -x, chúng tôi đang nói watchbỏ qua shell và thực hiện lệnh trực tiếp. Ngoài ra, bạn có thể làm:

watch 'exec gawk '\''
  FNR == 17 {nextfile}
  ENDFILE   {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}'\'' ./*'

Để watchchạy một shell sẽ mở rộng toàn ./*cầu đó ở mỗi lần lặp. watch foo barcó hiệu lực tương tự như watch -x sh -c 'foo bar'. Khi sử dụng watch -x, bạn có thể chỉ định shell nào bạn muốn và ví dụ, chọn shell mạnh hơn như thế zshcó thể thực hiện đệ quy đệ quy và giới hạn đối với các tệp thông thường:

watch -x zsh -c 'awk '\''...'\'' ./**/*(.)'

Không có gawk, bạn vẫn có thể làm một cái gì đó như:

watch '
  for file in ./*; do
    [ -s "$file" ] || continue
    printf "%s: " "$file"
    head -n 17 < "$file" | tail -n 1
  done'

Đưa ra một thông số như:

./file1: line17
./short-file2: line 5 is the last

Nhưng điều đó sẽ kém hiệu quả hơn rất nhiều vì nó ngụ ý chạy một số lệnh cho mỗi tệp.


Cảm ơn các lưu ý bảo mật. Trên thực tế, bạn đúng và lệnh của tôi cũng không làm những gì tôi cần, tức là xem các tệp đã thêm, phiên bản của bạn cũng giải quyết được. Nhược điểm duy nhất là tôi cần học AWK, mặc dù điều này sẽ được thực hiện với find . -exechoặc sth như thế này: D
Felix Dombek

11

Kết hợp headtailthích trong hai ví dụ sau:

$ seq 1 80 | head -n 17 | tail -n 1
17

$ seq 1 10 | head -n 17 | tail -n 1
10

Vì vậy, để giải quyết vấn đề thực tế của bạn, lệnh là:

watch 'for f in *; do head -n 17 -- "$f" 2>/dev/null | tail -n 1 ; done'

Lưu ý về 2>/dev/nullphần này, nó là cần thiết bởi vì * sẽ khớp với các thư mục và bất kỳ tệp nào bạn có thể không có quyền đọc, điều này sẽ tạo ra thông báo lỗi mà bạn có thể muốn ẩn.


0

một cách tiếp cận khác với find, exec và sed

watch find . -type f -name \"*\" -exec sh -c \'\( printf '%-50s ' {} \; sed -n 17p {}\)\' \\\;

1
Không hoạt động đối với các tệp có ít hơn 17 dòng. Đọc câu hỏi cẩn thận.
tự đại diệ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.