Liệt kê các tệp được sắp xếp theo số


123

Tôi có một loạt các tập tin từ log1đến log164.

Tôi đang cố gắng LIST thư mục (được sắp xếp) trong một thiết bị đầu cuối UNIX nhưng các hàm sắp xếp chỉ cung cấp định dạng như thế này:

home:logs Home$ ls -1 | sort
log1.gz
log10.gz
log100.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
...etc

Điều tôi muốn là

home:logs Home$ ls -1 | sort
log1.gz
log2.gz
log3.gz
log4.gz
log5.gz
log6.gz
log7.gz
...{more here}
log99.gz
log100.gz
log101.gz
log102.gz
...etc

Bất kỳ đề xuất trong những gì tôi có thể sử dụng để làm điều này?


8
Đây hoàn toàn là một câu hỏi lập trình và không đáng được di chuyển chỉ vì câu trả lời liên quan đến ngôn ngữ lập trình shell thấp !!!
tchrist

Nếu bạn biết trước rằng họ được đặt tên log1.gzthông qua log164.gz, thì bạn thậm chí cần ls -1họ để làm gì?
ruakh

1
@ruakh ls -1 hiển thị kết quả trong một cột thay vì ngang qua

3
@Rabiani: Tôi biết những gì ls -1hiện: nó liệt kê tên tệp. Vì bạn đã biết tên tập tin, tôi không hiểu bạn cần nó để làm gì. Nhưng vì bạn đã chấp nhận câu trả lời của Kevin, giờ tôi mới biết: bạn không cần nó. Mà có ý nghĩa hơn. :-)
ruakh

Câu trả lời:


40

bashniềng răng, {}sẽ liệt kê chúng theo thứ tự:

for file in log{1..164}.gz; do
    process "$file"
done

267

Tại sao không sử dụng được xây dựng trong lstính năng cho trường hợp cụ thể này, cụ thể là

-v natural sort of (version) numbers within text

Ví dụ ls -1v log*


Giải pháp tuyệt vời, mặc dù tôi muốn có một giải pháp đơn giản không kém bằng cách sử dụng sort, trong trường hợp một giải pháp có một chuỗi các chuỗi chứ không phải là một thư mục của các tệp
Hubro

23
Trên BSD / OSX tùy chọn này là một cái gì đó khác : -v - Force unedited printing of non-graphic characters.
kenorb

Thật không may, tùy chọn -v không khả dụng trên AIX (6.1)
bouvierr

6
Đây phải là câu trả lời tốt nhất.
32r34wgf3e

1
đối với MacOS, nó sẽ hoạt động, không thể tìm thấy một tùy chọn như đã đề cập, chỉls | sort -n
Ricky Levi

47

Với GNU ls (tức là trên Linux, Cygwin hoặc các hệ thống khác có GNU ls được cài đặt riêng):

ls -v

Trong zsh:

echo *(n)

Trong các vỏ khác:

echo log?.gz log??.gz log???.gz

Thay thế echobằng printf '%s\n'nếu bạn muốn mỗi tên tệp trên một dòng riêng biệt.

Nếu bạn cũng muốn siêu dữ liệu tệp ( ls -l) và bạn không có GNU ls, bạn sẽ cần gọi lsriêng cho từng tên tệp hoặc nhóm tên tệp mà bạn muốn xem theo thứ tự từ điển.

ls -ld log?.gz; ls -ld log??.gz; ls -ld log???.gz

Để tránh những khó khăn này, hãy sử dụng đủ các số 0 đứng đầu trong tên tệp của bạn để sắp xếp từ vựng thân thiện với con người ( log001.gz, v.v.).


29

Mặc dù giải pháp ls -1vnày chắc chắn là tốt nhất trong trường hợp cụ thể này, tôi nghĩ thật tốt khi có một giải pháp phù hợp sortnhư trong câu hỏi ban đầu, vì điều này cũng hoạt động khi đầu vào của bạn không đến ls. Trong trường hợp này, bạn có thể sử dụng:

ls -1 | sort -n -k1.4

Các -ntùy chọn cho loại để sắp xếp số lượng, và -k 1.4đặt phím sắp xếp để các trường đầu tiên (mà là toàn bộ tên tập tin trong trường hợp này) bắt đầu từ nhân vật thứ 4 cho đến cuối cùng.


Trong trường hợp của tôi, ls -1 | sort -n -k1.4không hoạt động. Nó đưa ra những cái chưa được sắp xếp lúc đầu lên đến 4 ký tự sau đó sắp xếp những ký tự sau ký tự thứ 4. Tôi đã sử dụng ls -1 |sort | sort -n -k1.4thay thế và nó hoạt động hoàn hảo.
Bohhu

3
@Prabhu, thay vào đó, bạn có thể làm sort -k1.1,1.3 -k1.4n. sortviệc triển khai không bắt buộc phải ổn định nên cách tiếp cận của bạn sẽ không hiệu quả với tất cả các triển khai. Xem thêm -Vtùy chọn của GNU và FreeBSD sort.
Stéphane Chazelas

21

GNU sort(như có sẵn trên Linux,) có chế độ "sắp xếp phiên bản" để diễn giải các số bên trong các số không theo cách bạn yêu cầu:

Từ man 1 sort:

    -V, --version-sort
           natural sort of (version) numbers within text

(Tạo các tệp kiểm tra trống để liệt kê
touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz:)

Trường hợp ví dụ của bạn, thêm -Vtùy chọn (hoặc --version-sort):

ls -1 log*.gz | sort -V
log1.gz
log2.gz
log3.gz
log99.gz
log100.gz
log101.gz
log102.gz


3

Phiên bản Solaris của tôi không hỗ trợ ls -v(grrr). Và giải pháp sắp xếp được cung cấp ở trên 1) đòi hỏi kiến ​​thức về vị trí của các chữ số trong tên tệp và 2) không xử lý những thứ như số phiên bản nhiều phần.

Cách tiếp cận bên dưới tương thích với Solaris, không yêu cầu biết trước các vị trí chữ số và xử lý số phiên bản với 2, 3 hoặc 4 thành phần (như: a-1.2, foo-5.6.7, bar_baz_9.10.11.12). Nó cũng sử dụng sort -fđể gấp chữ hoa và chữ thường lại với nhau và xử lý đúng các thư mục được trộn lẫn với các tệp:

ls -d | sort -f -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n

Lưu ý rằng phiên bản này giới hạn thành phần đầu tiên ở một chữ số.

Nếu (các) hệ điều hành mục tiêu của bạn hỗ trợ ls -v, đó rõ ràng là giải pháp ưu việt.


1

Giải pháp Perl:

ls log*.gz | perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; push @A, $_; END{ print sort { getnum $a <=> $b } @A}'

1
$ ls
log101.gz  log102.gz  log103.gz  log104.gz  log105.gz  log106.gz  log10.gz  log1.gz
$ ls | sort -t . -n -k1.4
log1.gz
log10.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz

1
Cái -t .này là thừa.
Stéphane Chazelas

0

Điều này làm việc cho tôi.

Tôi có tệp 1.jpg 2.jpg ... 18.jpg

$ echo *.jpg | tr -s ' ' '\n' | sort -n

sortđang bị lẫn lộn với lsđầu ra vì các ký tự màu không thể in được. Nếu bạn thử điều này:

ls -1 --color=none *.jpg | sort -n

nó sẽ hoạt động hoàn hảo

sortcó thể bỏ qua các ký tự không thể in được với -itùy chọn nhưng nó vẫn không hoạt động và tôi không biết tại sao.

Nhưng bạn luôn có thể lột màu như thế này và sortsẽ hoạt động:

ls -1 --color=always *.jpg | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sort -n

Tôi hy vọng một ngày nào đó sortsẽ có một lựa chọn cho việc này.

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.