ค้นหาไฟล์ล่าสุดตามวันที่แก้ไข


38

หากฉันต้องการค้นหาไฟล์ล่าสุด (mtime) ในไดเรกทอรี (ใหญ่) ที่มีไดเรกทอรีย่อยฉันจะทำอย่างไร

โพสต์จำนวนมากที่ฉันได้พบแนะนำรูปแบบบางอย่างของls -lt | head(ที่น่าแปลกใจหลายคำแนะนำls -ltr | tailที่เหมือนกัน แต่มีประสิทธิภาพน้อยกว่า) ซึ่งใช้ได้ดีเว้นแต่คุณจะมีไดเรกทอรีย่อย (ฉัน)

จากนั้นอีกครั้งคุณทำได้

find . -type f -exec ls -lt \{\} \+ | head

ซึ่งแน่นอนจะทำเคล็ดลับสำหรับไฟล์ได้มากเท่าที่สามารถระบุได้โดยคำสั่งเดียวเช่นถ้าคุณมีไดเรกทอรีขนาดใหญ่-exec...\+จะออกคำสั่งแยกต่างหาก ดังนั้นแต่ละกลุ่มจะถูกจัดเรียงด้วยlsตัวของมันเอง แต่ไม่เกินชุดรวม; หัวหน้าจะรับรายการล่าสุดของชุดแรก

คำตอบใด ๆ


btw คุณไม่จำเป็นต้องใช้แบ็กสแลชเหล่านั้นเลย
enzotib

@enzotib: คุณทำ ( \ + ) มิฉะนั้นคุณจะได้รับfind: missing argument to '-exec'
จัด

@ การจัดเรียง: ฉันไม่มีข้อผิดพลาดนี้ตามที่+ไม่มีความหมายbashดังนั้นไม่จำเป็นต้องหลบหนี
enzotib

@enzotib: ถูกต้องความผิดของฉันขอโทษ
จัด

คำตอบ:


46

คุณไม่จำเป็นต้องทำซ้ำคำสั่งภายนอก (ตามls) เพราะfindสามารถทำทุกอย่างที่คุณต้องการผ่านการ-printfกระทำ:

find /path -printf '%T+ %p\n' | sort -r | head

1
ใช่ฉันคิดfind . -type f -exec stat --format=%y \{\} \+ | sort -r | head -n1วิธีแก้ปัญหาของคุณสะอาดกว่า!
รวย

3
ต่อท้าย| cut -d ' ' -f2เพื่อรับชื่อไฟล์เท่านั้น
qwr

นอกจากนี้คุณยังสามารถเลือกเอาต์พุตheadเพื่อรวมจำนวนบรรทัดที่แน่นอน ฉันต้องการแค่บรรทัดแรกเท่านั้นดังนั้นฉันจึงใช้head -n 1
Timmah

8

ผมมีปัญหาที่คล้ายกันในวันนี้ findแต่ผมโจมตีได้โดยไม่ต้อง ฉันต้องการบางสิ่งสั้น ๆ ที่ฉันสามารถเรียกใช้sshเพื่อส่งคืนไฟล์ที่แก้ไขล่าสุดในไดเรกทอรีบ้าน นี่คือสิ่งที่ฉันคิดขึ้นมา:

ls -tp | grep -v /$ | head -1

-pตัวเลือกในการlsเพิ่มเฉือนท้ายไปยังไดเรกทอรีที่grep -vเส้นเอาลงท้ายด้วยการเฉือน (aka, ไดเรกทอรีทั้งหมด) และhead -1ข้อ จำกัด การส่งออกไปยังไฟล์เดียว

นี่คือ verbose น้อยกว่าการใช้findถ้าสิ่งที่คุณต้องการกลับคือชื่อไฟล์


สิ่งนี้ไม่ได้จัดการไดเรกทอรีย่อย
Clément

4

นี่เป็นระบบของฉันเร็วกว่าprintfแต่ฉันไม่เข้าใจว่าทำไม

find /path -type f -exec stat -c "%y %n" {} + | sort -r | head

ฉันยืนยันได้เร็วขึ้น
enzotib

อีกจุดหนึ่ง... | sort -r | head -n1 | cut -d " " -f 4-ถ้าคุณต้องการได้รับชื่อไฟล์เท่านั้น
林果皞

ฉันเพิ่งพบว่าsort -rผิดถ้ามีชื่อไฟล์ข้ามหลายบรรทัดอยู่
林果皞

2

แก้ไข: ฉันเดาว่าโพสต์นี้ไม่ 'ไม่มีประโยชน์อย่างยิ่ง' อย่างที่ฉันคิดว่ามันเป็น นี่เป็นวิธีแก้ปัญหาที่รวดเร็วมากที่เพิ่งติดตามไฟล์ที่แก้ไขล่าสุด (แทนที่จะเรียงลำดับรายการไฟล์ทั้งหมด):

find . -type f -printf '%T@ %p\n' | awk 'BEGIN { mostrecenttime = 0; mostrecentline = "nothing"; } { if ($1 > mostrecenttime) { mostrecenttime = $1; mostrecentline = $0; } } END { print mostrecentline; }' | cut -f2- -d ' '

กระจายไปบนหลายบรรทัดเพื่อความชัดเจน

find . -type f -printf '%T@ %p\n' | awk '
    BEGIN { mostrecenttime = 0; mostrecentline = "nothing"; }
    {
        if ($1 > mostrecenttime)
            { mostrecenttime = $1; mostrecentline = $0; }
    }
    END { print mostrecentline; }' | cut -f2- -d ' '

สิ้นสุดการแก้ไข


ไม่ใช่โพสต์ที่มีประโยชน์โดยเฉพาะ แต่เนื่องจาก 'จัดการ' กำลังพูดถึงความเร็วฉันคิดว่าฉันจะแชร์สิ่งนี้

วิธีแก้ปัญหาการจัดเรียงและ enzotib เกี่ยวข้องกับการแสดงรายการไฟล์ทั้งหมดในไดเรกทอรีที่มี mtimes ของพวกเขาและจากนั้นเรียงลำดับ ในขณะที่คุณรู้ว่าการเรียงลำดับไม่จำเป็นต้องค้นหาค่าสูงสุด การค้นหาสูงสุดสามารถทำได้ในเวลาเชิงเส้น แต่การเรียงลำดับต้องใช้เวลา n บันทึก (n) เวลา [ฉันรู้ว่าความแตกต่างนั้นไม่มาก แต่ก็ยัง;)] ฉันคิดไม่ออกว่าจะนำสิ่งนี้ไปใช้อย่างไร [แก้ไข: ดูเรียบร้อย (แม้ว่าจะดูสกปรก) และมีการนำไปใช้อย่างรวดเร็วด้านบน]

สิ่งที่ดีที่สุดถัดไป - หากต้องการค้นหาไฟล์ที่แก้ไขล่าสุดในไดเรกทอรีให้ค้นหาไฟล์ที่แก้ไขล่าสุดซ้ำในไดเรกทอรีย่อยระดับ 1 แต่ละรายการ ให้ไฟล์นี้เป็นตัวแทนไดเรกทอรีย่อย ตอนนี้เรียงลำดับไฟล์ระดับ 1 พร้อมกับตัวแทนของไดเรกทอรีย่อยระดับ 1 หากจำนวนไฟล์ระดับ 1 และไดเร็กตอรีย่อยของแต่ละไดเร็กทอรีใกล้เคียงกับค่าคงที่กระบวนการนี้ควรปรับขนาดเชิงเส้นด้วยจำนวนไฟล์ทั้งหมด

นี่คือสิ่งที่ฉันคิดขึ้นมาเพื่อใช้สิ่งนี้:

findrecent() { { find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1; }
findrecent .

ฉันวิ่งและได้รับfind: findrecent: No such file or directoryข้อผิดพลาดมากมาย เหตุผล: -exec of find run ในเชลล์ที่ต่างกัน ฉันพยายามกำหนด findrecent เป็น. bashrc, .xsessionrc แต่สิ่งเหล่านี้ไม่ได้ช่วย [ฉันขอขอบคุณที่นี่] ในที่สุดฉันก็หันไปใส่

#!/bin/bash
{ find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1;

ในสคริปต์ที่เรียกว่าfindrecentในเส้นทางของฉันแล้วเรียกใช้

ฉันวิ่งสิ่งนี้รอต่อไปและรอโดยไม่มีเอาต์พุต เพียงเพื่อให้แน่ใจว่าฉันไม่ได้จัดการกับลูปไม่ จำกัด ใด ๆ ที่ฉันแก้ไขไฟล์เป็น

#!/bin/bash
echo "$1" >&2
{ find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1;

และลองอีกครั้ง มันใช้งานได้ - แต่ใช้เวลา 1 นาที 35 วินาทีในบ้านของฉัน - วิธีการแก้ปัญหาและการจัดเรียงของ enzotib ใช้เวลา 1.69, 1.95 วินาทีตามลำดับ!

มากสำหรับ O (n) เหนือกว่า O (n log (n))! ประณามคุณเรียกใช้ค่าใช้จ่าย! [หรือมากกว่าการเรียกใช้สคริปต์]

แต่สคริปต์นี้ทำงานได้ดีกว่าโซลูชันก่อนหน้านี้และฉันคิดว่ามันจะทำงานได้เร็วกว่าในหน่วยความจำของ Google; D


2

ใช้perlใน conjonctin กับfind:

 find my_directory -type f -printf '%T@\t%p\n' | perl -ane '@m=@F if ($F[0]>$m[0]); END{print $m[1];}'

คุณได้รับชื่อไฟล์ด้วย epoch ที่ยิ่งใหญ่ที่สุด == แก้ไขไฟล์ล่าสุด


1

มันไม่ได้เกือบจะเป็นแฟชั่น แต่ก็เป็นไปได้ที่จะบรรลุสิ่งนี้ด้วยMidnight Commander : ค้นหา *, จัดเรียงผล, เรียงลำดับตามเวลาการแก้ไขเรียงตามลำดับย้อนหลัง

เห็นได้ชัดว่ามันช้ากว่าfind- ไดเรกทอรีบ้านของฉันที่มีไฟล์ 922000 เรียงลำดับmcในเกือบ 14 นาทีในขณะที่findใช้เวลาน้อยกว่า 5 - แต่มีประโยชน์บางอย่าง:

  • ฉันอาจใช้เวลานานกว่านั้นความต่างกัน 9 นาทีในการประดิษฐ์การค้นหาที่เหมาะสม :)

  • โอกาสที่จะเกิดข้อผิดพลาดน้อยลง (ลืมระบุ -r สำหรับการเรียงลำดับ ฯลฯ - เริ่มใหม่อีกครั้ง)

  • เป็นไปได้ที่จะเล่นกับชุดผลลัพธ์โดยเปลี่ยนลำดับการเรียง ฯลฯ - โดยไม่ต้องสอบถามไฟล์ซ้ำ

  • เป็นไปได้ที่จะดำเนินการกับไฟล์ในไฟล์บางไฟล์จากชุดผลลัพธ์ - เช่นเรียงตามขนาดลบไฟล์ขนาดใหญ่บางไฟล์ซึ่งไม่จำเป็น

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