วิธีการวนซ้ำไฟล์ที่ถูกแก้ไขล่าสุดในไดเรกทอรีซ้ำ?


242

ดูเหมือนว่าlsจะไม่เรียงลำดับไฟล์อย่างถูกต้องเมื่อทำการโทรซ้ำ:

ls -altR . | head -n 3

ฉันจะค้นหาไฟล์ที่แก้ไขล่าสุดในไดเรกทอรี (รวมถึงไดเรกทอรีย่อย) ได้อย่างไร


คำตอบ:


357
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "

สำหรับต้นไม้ใหญ่มันอาจยากที่sortจะเก็บทุกอย่างไว้ในความทรงจำ

%T@ให้เวลาในการแก้ไขเช่นการประทับเวลายูนิกซ์sort -nเรียงตามตัวเลขtail -1ใช้บรรทัดสุดท้าย (การประทับเวลาสูงสุด) cut -f2 -d" "ตัดฟิลด์แรก (การประทับเวลา) ออกจากเอาต์พุต

แก้ไข:เช่นเดียวกับที่ใช้ใน-printfGNU เท่านั้นการใช้ ajreals ของstat -cก็เช่นกัน แม้ว่ามันจะเป็นไปได้ที่จะทำเช่นเดียวกันใน BSD ตัวเลือกสำหรับการจัดรูปแบบแตกต่างกัน ( -f "%m %N"มันจะดูเหมือน)

และฉันพลาดส่วนที่เป็นพหูพจน์ ถ้าคุณต้องการที่มากขึ้นแล้วไฟล์ล่าสุดเพียงชนขึ้นโต้แย้งหาง


7
หากคำสั่งซื้อที่สำคัญคุณสามารถสลับการใช้งานแทนsort -rn | head -3 sort -n | tail -3หนึ่งเวอร์ชันให้ไฟล์จากเก่าไปหาใหม่ในขณะที่อีกรุ่นหนึ่งเปลี่ยนจากใหม่สุดไปหาเก่าที่สุด
Don Faulkner

3
ฉันมีไดเรกทอรีขนาดใหญ่ (ไฟล์เล็ก ๆ น้อยหมื่น) และฉันกังวลเกี่ยวกับประสิทธิภาพ แต่ ... คำสั่งนี้ทำงานในเวลาน้อยกว่าหนึ่งวินาที! เยี่ยมมากขอบคุณมาก !!! :-)
lucaferrario

2
"สำหรับต้นไม้ใหญ่มันอาจจะยากสำหรับการจัดเรียงเพื่อเก็บทุกอย่างไว้ในความทรงจำ" sortจะสร้างไฟล์ชั่วคราว ( /tmpเป็น) ตามที่ต้องการดังนั้นฉันไม่คิดว่าเป็นปัญหา
Vladimir Panteleev

1
การปรับเปลี่ยนเป็น: -printf '%T@ %Tb %Td %TY %p\n'จะให้การประทับวันที่ (ถ้าจำเป็น) (คล้ายกับls)
bshea

1
ฉันพบต่อไปนี้สั้นกว่าและมีผลผลิต interpretable เพิ่มเติมได้ที่:find . -type f -printf '%TF %TT %p\n' | sort | tail -1
snth

129

ติดตามคำตอบของ @ plundraต่อไปนี้เป็นเวอร์ชั่น BSD และ OS X:

find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "

1
BSD / OS X findรองรับ+แทนได้\;หรือไม่? เพราะนั่นทำสิ่งเดียวกัน (ผ่านหลายไฟล์เป็นพารามิเตอร์) โดยไม่ต้อง-print0 | xargs -0ไพพ์
DevSolar

จะทำอย่างไรถ้าฉันต้องการได้รับไฟล์ 5 หรือ n ไฟล์ที่แก้ไขล่าสุดตามลำดับจากมากไปน้อย
khunshan

@khunshan เปลี่ยนhead -1ไปhead -5
เมอร์สัน Farrugia

20

แทนที่จะเรียงลำดับผลลัพธ์และเก็บไว้เฉพาะรายการที่แก้ไขล่าสุดคุณสามารถใช้ awk เพื่อพิมพ์เฉพาะรายการที่มีเวลาแก้ไขมากที่สุด (ในเวลา unix):

find . -type f -printf "%T@\0%p\0" | awk '
    {
        if ($0>max) {
            max=$0; 
            getline mostrecent
        } else 
            getline
    } 
    END{print mostrecent}' RS='\0'

นี่ควรเป็นวิธีที่เร็วกว่าในการแก้ปัญหาของคุณหากจำนวนไฟล์มีขนาดใหญ่พอ

ฉันได้ใช้อักขระ NUL (เช่น '\ 0') เพราะในทางทฤษฎีชื่อไฟล์อาจมีอักขระใด ๆ (รวมถึงช่องว่างและขึ้นบรรทัดใหม่) แต่ที่จริงแล้ว

หากคุณไม่มีชื่อไฟล์พยาธิวิทยาดังกล่าวในระบบของคุณคุณสามารถใช้อักขระขึ้นบรรทัดใหม่ได้เช่นกัน:

find . -type f -printf "%T@\n%p\n" | awk '
    {
        if ($0>max) {
            max=$0; 
            getline mostrecent
        } else 
            getline
    } 
    END{print mostrecent}' RS='\n'

นอกจากนี้ยังใช้งานได้ใน mawk ด้วย


สิ่งนี้สามารถปรับเปลี่ยนได้อย่างง่ายดายเพื่อให้ทั้งสามล่าสุด
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

1
สิ่งนี้ใช้ไม่ได้กับmawkตัวเลือกมาตรฐาน Debian
ม.ค.

ไม่ แต่ในกรณีนี้คุณสามารถใช้อักขระขึ้นบรรทัดใหม่หากไม่ทำให้คุณรำคาญ);
marco

10

ฉันมีปัญหาในการค้นหาไฟล์ที่แก้ไขล่าสุดภายใต้ Solaris 10 findไม่มีprintfตัวเลือกและstatไม่สามารถใช้งานได้ ฉันค้นพบวิธีแก้ไขปัญหาต่อไปนี้ซึ่งทำงานได้ดีสำหรับฉัน:

find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7 }' | sort | tail -1

เพื่อแสดงชื่อไฟล์เช่นกันใช้

find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1

คำอธิบาย

  • find . -type f ค้นหาและแสดงรายการไฟล์ทั้งหมด
  • sed 's/.*/"&"/' ล้อมชื่อพา ธ ในเครื่องหมายคำพูดเพื่อจัดการกับช่องว่าง
  • xargs ls -Eส่งเส้นทางที่ยกมาไปlsยัง-Eตัวเลือกทำให้แน่ใจว่าการประทับเวลาเต็มรูปแบบ (รูปแบบปีเดือนเดือนวันชั่วโมงนาทีวินาทีนาโนวินาที ) จะถูกส่งกลับ
  • awk '{ print $6," ",$7 }' แยกเฉพาะวันที่และเวลา
  • awk '{ print $6," ",$7," ",$9 }' แยกวันที่เวลาและชื่อไฟล์
  • sort ส่งคืนไฟล์ที่เรียงลำดับตามวันที่
  • tail -1 ส่งคืนเฉพาะไฟล์ที่แก้ไขล่าสุด

9

ดูเหมือนว่าจะทำงานได้ดีแม้จะมีไดเรกทอรีย่อย:

find . -type f | xargs ls -ltr | tail -n 1

ในกรณีที่มีไฟล์มากเกินไปให้ปรับแต่งการค้นหา


1
-lตัวเลือกที่จะlsดูเหมือนว่าไม่จำเป็น เพียงแค่-trดูเหมือนว่าเพียงพอ
คิวเมนตัส

6
ดูเหมือนว่าจะเรียงลำดับต่อไดเรกทอรีดังนั้นจึงไม่จำเป็นต้องแสดงไฟล์ล่าสุด
Fabian Schmengler

1
ในกรณีที่มีช่องว่างในไฟล์พา ธ ทำได้ดีกว่า:find . -type f -print0 | xargs -0 ls -ltr | tail -n 1
บำรุงรักษาเป็นระยะ

ไม่พบไฟล์ล่าสุดสำหรับฉัน
K. -Michael Aye

1
คิดว่าตัวแบ่งนี้ถ้ามีช่องว่างในชื่อไฟล์
waferthin

7

แสดงไฟล์ล่าสุดพร้อมเวลาประทับที่มนุษย์อ่านได้:

find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1

ผลลัพธ์มีลักษณะเช่นนี้:

2015-10-06 11:30: +0200 ./foo/bar.txt

หากต้องการแสดงไฟล์เพิ่มเติมให้แทนที่-n1ด้วยจำนวนที่สูงกว่า


5

ฉันใช้สิ่งที่คล้ายกันตลอดเวลารวมถึงรายการ top-k ของไฟล์ที่แก้ไขล่าสุด สำหรับต้นไม้ไดเรกทอรีขนาดใหญ่ก็อาจจะได้เร็วขึ้นมากเพื่อหลีกเลี่ยงการเรียงลำดับ ในกรณีของไฟล์เพิ่งมีการแก้ไขมากที่สุดอันดับ 1:

find . -type f -printf '%T@ %p\n' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'

ในไดเรกทอรีที่มีไฟล์ 1.7 ล้านไฟล์ฉันได้รับไฟล์ล่าสุดใน 3.4 วินาทีเพิ่มความเร็ว 7.5 เท่าเทียบกับโซลูชัน 25.5 โดยใช้การเรียงลำดับ


เจ๋งมาก: ฉันเพิ่งแลกเปลี่ยนการพิมพ์ล่าสุดกับ: ระบบ ("ls -l $ f") ถ้า eof () เพื่อดูวันที่ด้วยวิธีที่ดีเช่นกัน
Martin T.

@MartinT : ยอดเยี่ยมและยินดีต้อนรับ มันแปลกสำหรับฉันที่ผู้คนมีสัญชาตญาณในการจัดเรียงสิ่งต่าง ๆ (O (n log n)) เมื่อมีวิธี O (n) นี่เป็นคำตอบเดียวที่หลีกเลี่ยงการเรียงลำดับ BTW เป้าหมายของคำสั่งที่ฉันแนะนำคือเพียงหาเส้นทางของไฟล์ล่าสุด คุณสามารถนามแฝงคำสั่งในเปลือกของคุณ (เช่นเป็นlastfile) และจากนั้นคุณสามารถทำสิ่งที่คุณต้องการกับผลลัพธ์เช่นls -l $(lastfile .)หรือopen $(lastfile .)(สำหรับ Mac) ฯลฯ
Pierre D

โอ้ฉันยืนแก้ไข: ฉันเห็นคำตอบอื่นด้านล่าง (@marco) +1
Pierre D

4

นี่จะให้รายการเรียงลำดับ:

find . -type f -ls 2>/dev/null | sort -M -k8,10 | head -n5

กลับคำสั่งซื้อโดยการวาง '-r' ในคำสั่ง sort หากคุณต้องการชื่อไฟล์เพียงแทรก "awk '{print $ 11}' |" ก่อนหน้า '| ศีรษะ'


3

บน Ubuntu 13 ต่อไปนี้อาจจะเร็วกว่าเล็กน้อยเนื่องจากจะสลับการเรียงลำดับและใช้ 'head' แทน 'tail' เพื่อลดการทำงาน ในการแสดงไฟล์ใหม่ล่าสุด 11 ไฟล์ในแผนผัง:

หา -type f -printf '% T @% p \ n' | sort -n -r | หัว -11 | ตัด -f2- -d "" | sed -e 's, ^. / ,,' | xargs ls -U -l

สิ่งนี้จะช่วยให้รายการ ls สมบูรณ์โดยไม่ต้องเรียงใหม่และละเว้น './' ที่ 'find' ที่สร้างความรำคาญให้กับทุกชื่อไฟล์

หรือเป็นฟังก์ชันทุบตี:

treecent () {
  local numl
  if [[ 0 -eq $# ]] ; then
    numl=11   # Or whatever default you want.
  else
    numl=$1
  fi
  find . -type f -printf '%T@ %p\n' | sort -n -r | head -${numl} |  cut -f2- -d" " | sed -e 's,^\./,,' | xargs ls -U -l
}

ถึงกระนั้นงานส่วนใหญ่ก็ทำโดยวิธีดั้งเดิมของ plundra ขอขอบคุณทุนดรา


3

ฉันประสบปัญหาเดียวกัน ฉันต้องการค้นหาไฟล์ล่าสุดซ้ำ ๆ หาใช้เวลาประมาณ 50 นาทีในการค้นหา

นี่เป็นสคริปต์เล็กน้อยที่จะทำให้เร็วขึ้น:

#!/bin/sh

CURRENT_DIR='.'

zob () {
    FILE=$(ls -Art1 ${CURRENT_DIR} | tail -n 1)
    if [ ! -f ${FILE} ]; then
        CURRENT_DIR="${CURRENT_DIR}/${FILE}"
        zob
    fi
    echo $FILE
    exit
}
zob

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


3

ฉันพบว่าสั้นลงและมีผลลัพธ์ที่ตีความได้มากขึ้น:

find . -type f -printf '%TF %TT %p\n' | sort | tail -1

เมื่อกำหนดความยาวคงที่ของชุดข้อมูลรูปแบบ ISO มาตรฐานการเรียงลำดับพจนานุกรมจะใช้ได้และเราไม่ต้องการ-nตัวเลือกในการเรียงลำดับ

หากคุณต้องการลบการประทับเวลาอีกครั้งคุณสามารถใช้:

find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '

2

หากการเรียกใช้statไฟล์แต่ละไฟล์นั้นช้าลงคุณสามารถใช้xargsเพื่อเพิ่มความเร็วให้กับบิต:

find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" " 

2

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

for dir in */; do find $dir -type f -printf '%T@ "%p"\n' | sort -n | tail -1 | cut -f2- -d" " | xargs -I {} touch -r {} $dir; done

1
มันจะแบ่งไม่ดีถ้า dirs ใด ๆ มีช่องว่าง - จำเป็นต้องตั้งค่า IFS และใช้เครื่องหมายคำพูด: IFS = $ '\ n'; สำหรับ dir ใน $ (find ./ -type d); ทำเสียงสะท้อน "$ dir"; ค้นหา "$ dir" - พิมพ์ f -printf '% T @ "% p" \ n' | เรียง -n | หาง -1 | ตัด -f2- -d "" | xargs -I {} touch -r {} "$ dir"; ทำ;
Andy Lee Robinson

2

cli แบบง่ายนี้จะทำงาน:

ls -1t | head -1

คุณสามารถเปลี่ยน -1 เป็นจำนวนไฟล์ที่คุณต้องการแสดงรายการ


10
ไม่มันจะไม่ทำตามที่ไม่ซ้ำ
arataj

1

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

find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l


1

ไม่สนใจไฟล์ที่ซ่อน - พร้อมการประทับเวลาที่ดี & รวดเร็ว

$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10

ผลลัพธ์

จัดการช่องว่างในชื่อไฟล์ได้ดี - ไม่ใช่ว่าควรใช้สิ่งเหล่านี้!

2017.01.25 18h23 Wed ./indenting/Shifting blocks visually.mht
2016.12.11 12h33 Sun ./tabs/Converting tabs to spaces.mht
2016.12.02 01h46 Fri ./advocacy/2016.Vim or Emacs - Which text editor do you prefer?.mht
2016.11.09 17h05 Wed ./Word count - Vim Tips Wiki.mht

มากกว่า

อีก findมากมายตามลิงค์


1

ในการค้นหาไฟล์ใน / target_directory และไดเรกทอรีย่อยทั้งหมดที่ได้รับการแก้ไขใน 60 นาทีล่าสุด:

$ find /target_directory -type f -mmin -60

หากต้องการค้นหาไฟล์ที่แก้ไขล่าสุดเรียงลำดับตามเวลาย้อนหลังของเวลาอัปเดต (เช่นไฟล์ที่อัปเดตล่าสุดก่อน):

$ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r


0

ฉันเขียน pypi / github package สำหรับคำถามนี้เพราะฉันต้องการทางออกด้วย

https://github.com/bucknerns/logtail

ติดตั้ง:

pip install logtail

การใช้งาน: ก้อยเปลี่ยนไฟล์

logtail <log dir> [<glob match: default=*.log>]

การใช้งาน 2: เปิดไฟล์ที่เปลี่ยนแปลงล่าสุดในเครื่องมือแก้ไข

editlatest <log dir> [<glob match: default=*.log>]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.