Làm thế nào để sắp xếp các tập tin theo một phần của tên tệp?


7

Đưa ra các tập tin dưới đây:

ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP
XYZ38390.SC00.Statue_WKP

Làm thế nào tôi có thể liệt kê tất cả dựa trên SCgiá trị, như thế này:

XYZ38390.SC00.Statue_WKP
ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP

Câu trả lời:


8

Trong trường hợp cụ thể này khi tên tệp của bạn không chứa bất kỳ khoảng trắng hoặc ký tự lạ nào khác, bạn có thể sử dụng lsvà chuyển nó qua sort:

$ ls -d -- *.SC* | sort -t. -k2
XYZ38390.SC00.Statue_WKP
ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP

Các -tbộ lĩnh vực delimiter và -k2nói sortđể sắp xếp dựa trên một phần của dòng bắt đầu với 2 nd lĩnh vực (sử dụng -k2,2cho trường thứ hai chỉ ).

Đối với các trường hợp phức tạp hơn, bạn có thể in từng tên tệp theo sau là ký tự NULL ( \0), sau đó chuyển sang GNU sortbằng -ztùy chọn của nó để yêu cầu nó đọc các dòng được phân cách bằng NULL và cuối cùng, sử dụng trđể thay đổi \0ngược lại thành \n:

printf '%s\0' *SC* | sort -zt. -k2 | tr '\0' '\n'

Cảm ơn tất cả ... "-k" tham số sắp xếp gây nhầm lẫn cho tôi ... trên cơ sở nào nó đã chọn trường làm tôi bối rối ... như k2 cho trường thứ hai?
MRKR

@MRKR -t.bảo nó sử dụng .làm dấu tách trường để tham chiếu -k2đến trường thứ hai như được định nghĩa bởi ..
terdon

@MRKR Nếu một trong những câu trả lời ở đây giải quyết được vấn đề của bạn, vui lòng dành chút thời gian và chấp nhận nó bằng cách nhấp vào dấu kiểm bên trái. Điều đó sẽ đánh dấu câu hỏi đã được trả lời và là cách cảm ơn được thể hiện trên các trang web Stack Exchange.
terdon

4

Với zsh, bạn có thể xác định thứ tự sắp xếp của riêng mình cho các khối với các vòng loại oehoặc toàn o+cầu:

ls -lUd -- *(oe['REPLY=${REPLY#*.SC}'])

hoặc là:

bysc() REPLY=${REPLY#*.SC}
ls -lUd -- *(o+bysc)

Hàm sắp xếp nhận tên tệp trong $REPLYvà có nghĩa là trả về một chuỗi trong $REPLYthế giới đó sẽ sắp xếp. Ở đây, chúng tôi trả lại một phần tên tệp ở bên phải của lần xuất hiện đầu tiên của .SC(hoặc tên tệp đầy đủ nếu nó không chứa .SC).


1

Trên hệ thống GNU và có zshhoặc bashnhư vỏ của bạn, hãy sử dụng:

find -maxdepth 1 -type f -print0 | sort -z -t. -k3 | \
while IFS="" read -r -d "" f; do
  basename "$f"
done

  • findtìm kiếm các tệp trong thư mục hiện tại ( -maxdepth 1) và in chúng được phân tách bằng byte ( -print0).
  • sortđọc đầu vào null-byte được phân cách ( -z) và sắp xếp trên một phần của bản ghi bắt đầu trên trường thứ 3 ( -k3) cách nhau bởi dấu chấm ( -t.).
  • while đọc đầu vào
    • basenamein tên của nó mà không có đường dẫn

0

Tôi sẽ - như tôi thường làm - đề nghị perl.

perlcó một chức năng sắp xếp cho phép bạn chỉ định một chức năng so sánh. Chức năng so sánh này là bất kỳ bài kiểm tra đó có hai giá trị, và trở lại -1, 0hoặc 1tùy thuộc vào vị trí tương đối.

Nó lặp lại danh sách thiết lập từng giá trị $a$bvà 'thực hiện kiểm tra' cho từng thành phần.

Vì vậy, theo mặc định:

$a cmp $b 

để so sánh theo chuỗi, hoặc sort { $a <=> $b }cho số.

Nhưng kết quả là, bạn có thể áp dụng các tiêu chí sắp xếp tùy chỉnh phức tạp tùy ý:

#!/usr/bin/perl
use strict;
use warnings;

sub sort_by_sc {
   my ( $a_sc ) = $a =~ m/SC(\d+)/;
   my ( $b_sc ) = $b =~ m/SC(\d+)/;
   return $a_sc <=> $b_sc;
}


my @file_list = qw ( 
    ABC38388.SC01.StatueGrade_MKP
    ABC38388.SC02.Statue_GKP
    DEF38389.SC03.Statue_HKP
    XYZ38390.SC00.Statue_WKP
);

print sort sort_by_sc @file_list;

Hoặc được giảm xuống thành một lớp lót, đọc STDINhoặc một tệp (được phân tách bằng dòng, thường là đủ tốt):

perl -e 'print sort {@x = map {/SC(\d+)/}($a,$b); $x[0] <=> $x[1]} <>'

Thay vào đó, bạn có thể cung cấp cho nó kết quả của globmẫu thư mục thay thế:

perl -e 'print sort {@x = map {/SC(\d+)/}($a,$b); $x[0] <=> $x[1]} glob ( "*SC*")'
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.