รายการไฟล์ที่เรียงลำดับตัวเลข


122

ฉันมีพวงของไฟล์จากไปlog1log164

ฉันพยายามที่จะแสดงรายการไดเรกทอรี (เรียงลำดับ) ในเทอร์มินัล UNIX แต่ฟังก์ชั่นการเรียงลำดับจะให้รูปแบบดังนี้:

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

สิ่งที่ฉันต้องการคือ

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

ข้อเสนอแนะใด ๆ ในสิ่งที่ฉันสามารถใช้เพื่อทำสิ่งนี้?


8
นี่เป็นคำถามการเขียนโปรแกรมอย่างแน่นอนและไม่ควรถูกโยกย้ายเพียงเพราะคำตอบนั้นเกี่ยวข้องกับภาษาการเขียนโปรแกรมเชลล์ต่ำต้อย !!!
tchrist

หากคุณรู้ล่วงหน้าว่าพวกเขาตั้งชื่อlog1.gzผ่านlog164.gzคุณจะต้องls -1ทำอะไร
ruakh

1
@ruakh ls -1 แสดงผลลัพธ์ในหนึ่งคอลัมน์แทนที่จะข้าม

3
@Rabiani: ฉันรู้ว่าls -1มันทำอะไร: มันแสดงชื่อไฟล์ เมื่อคุณรู้จักชื่อไฟล์แล้วฉันไม่เข้าใจสิ่งที่คุณต้องการ แต่เมื่อคุณยอมรับคำตอบของเควินฉันรู้แล้วว่าคุณไม่ต้องการมัน ซึ่งทำให้รู้สึกมากขึ้น :-)
ruakh

คำตอบ:


40

bashเครื่องหมายวงเล็บของ, {}จะระบุให้เรียงตามลำดับ:

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

266

ทำไมไม่ใช้lsคุณสมบัติในตัวสำหรับกรณีนี้คือ

-v natural sort of (version) numbers within text

ตัวอย่างเช่น ls -1v log*


วิธีแก้ปัญหาที่น่ากลัว แต่ฉันหวังว่าจะมีวิธีการแก้ปัญหาที่เรียบง่ายอย่างเท่าเทียมกันsortในกรณีที่มีอาร์เรย์ของสตริงแทนที่จะเป็นไดเรกทอรีไฟล์
Hubro

23
เมื่อวันที่ BSD / OSX -v - Force unedited printing of non-graphic charactersตัวเลือกนี้เป็นอย่างอื่น:
kenorb

น่าเสียดายที่อ็อพชัน -v ไม่พร้อมใช้งานบน AIX (6.1)
bouvierr

6
นี่ควรเป็นคำตอบที่ดีที่สุด
32r34wgf3e

1
สำหรับ MacOS สิ่งนี้จะใช้งานไม่พบตัวเลือกตามที่กล่าวไว้เท่านั้นls | sort -n
Ricky Levi

47

ด้วย GNU ls (เช่นบน Linux, Cygwin หรือระบบอื่น ๆ ที่ติดตั้ง GNU ls ไว้โดยเฉพาะ):

ls -v

ใน zsh:

echo *(n)

ในเปลือกหอยอื่น ๆ :

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

แทนที่echoด้วยprintf '%s\n'หากคุณต้องการชื่อไฟล์แต่ละชื่อในบรรทัดแยกต่างหาก

หากคุณต้องการข้อมูลเมตาของไฟล์เช่นกัน ( ls -l) และคุณไม่มี GNU ls คุณจะต้องโทรlsแยกต่างหากสำหรับแต่ละชื่อไฟล์หรือกลุ่มชื่อไฟล์ที่คุณต้องการดูตามลำดับพจนานุกรม

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

เพื่อหลีกเลี่ยงปัญหาเหล่านี้ให้ใช้เลขศูนย์นำหน้าพอในชื่อไฟล์ของคุณเพื่อให้การเรียงลำดับพจนานุกรมเป็นมิตรกับมนุษย์ ( log001.gzฯลฯ )


29

ในขณะที่การแก้ปัญหาls -1vเป็นที่แน่นอนแล้วว่าอร่อยที่สุดในกรณีนี้โดยเฉพาะอย่างยิ่งผมคิดว่ามันเป็นเรื่องดีที่ยังมีคนที่ทำงานร่วมกับในขณะที่คำถามเดิมตั้งแต่นี้ทำงานเมื่อป้อนข้อมูลของคุณไม่ได้มาจากsort lsในกรณีนี้คุณสามารถใช้:

ls -1 | sort -n -k1.4

-nตัวเลือกที่บอกการเรียงลำดับการเรียงลำดับตัวเลขและ-k 1.4ชุดที่สำคัญการจัดเรียงเพื่อฟิลด์แรก (ซึ่งเป็นชื่อไฟล์ทั้งหมดในกรณีนี้) เริ่มต้นจากตัวละครที่ 4 ขึ้นไปยังหน้าล่าสุด


ในกรณีของฉันls -1 | sort -n -k1.4ไม่ทำงาน มันให้คนที่ไม่เรียงลำดับในตอนแรกจนถึง 4 ตัวอักษรจากนั้นเรียงลำดับหลังจากอักขระที่ 4 ฉันใช้ls -1 |sort | sort -n -k1.4แทนและมันทำงานได้อย่างสมบูรณ์
Prabhu

3
@Prabhu sort -k1.1,1.3 -k1.4nแทนคุณสามารถทำ sortการใช้งานไม่จำเป็นต้องมีเสถียรภาพดังนั้นวิธีการของคุณจะไม่ทำงานกับการใช้งานทั้งหมด ดูเพิ่มเติม-Vตัวเลือกของ GNU และ sortFreeBSD
Stéphane Chazelas

21

GNU sort(พร้อมใช้งานบน Linux) มีโหมด "การเรียงลำดับเวอร์ชัน" ที่ตีความหมายเลขภายในที่ไม่ใช่ตัวเลขตามที่คุณขอ:

จากman 1 sort:

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

(การสร้างแฟ้มการทดสอบที่ว่างเปล่า to list:
touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz)

กรณีตัวอย่างของคุณเพิ่ม-Vตัวเลือก (หรือ--version-sort):

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


3

Solaris รุ่นของฉันไม่รองรับls -v(grrr) และโซลูชันการเรียงลำดับที่ให้ไว้ด้านบน 1) ต้องการความรู้เกี่ยวกับตำแหน่งของตัวเลขในชื่อไฟล์และ 2) ไม่จัดการกับสิ่งต่าง ๆ เช่นหมายเลขรุ่นหลายส่วน

วิธีการด้านล่างนี้ใช้ร่วมกับ Solaris ได้โดยไม่จำเป็นต้องรู้ล่วงหน้าเกี่ยวกับตำแหน่งหลักและจัดการหมายเลขรุ่นที่มีส่วนประกอบ 2, 3 หรือ 4 (เช่น: a-1.2, foo-5.6.7, bar_baz_9.10.11.12) นอกจากนี้ยังใช้sort -fเพื่อพับส่วนบนและตัวพิมพ์เล็กเข้าด้วยกันและจัดการไดเรกทอรีที่ผสมกับไฟล์ได้อย่างเหมาะสม:

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

โปรดทราบว่ารุ่นนี้ จำกัด องค์ประกอบแรกให้เป็นตัวเลขหลักเดียว

หากระบบปฏิบัติการเป้าหมายของคุณรองรับls -vนั่นเป็นโซลูชันที่เหนือกว่า



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
-t .เป็นฟุ่มเฟือยที่นี่
Stéphane Chazelas

0

สิ่งนี้ใช้ได้สำหรับฉัน

ฉันมีไฟล์ 1.jpg 2.jpg ... 18.jpg

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

sortกำลังสับสนกับlsผลลัพธ์เนื่องจากอักขระสีที่ไม่สามารถพิมพ์ได้ หากคุณลองทำสิ่งนี้:

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

มันจะทำงานได้อย่างสมบูรณ์แบบ

sortสามารถละเว้นอักขระที่ไม่สามารถพิมพ์ได้ด้วย-iตัวเลือก แต่ก็ยังใช้งานไม่ได้และฉันไม่รู้ว่าทำไม

แต่คุณสามารถตัดสีแบบนี้ได้และsortจะทำงาน:

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

ฉันหวังว่าสักวันหนึ่งsortจะมีตัวเลือกสำหรับสิ่งนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.