วิธีแสดงรายการไฟล์ที่เรียงลำดับตามวันที่แก้ไขซ้ำ ๆ (ไม่มีคำสั่งสถิติให้ใช้!)


31

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

ตอนนี้ฉันรู้วิธีการที่จะประสบความสำเร็จที่มีfind, statและsortแต่ด้วยเหตุผลแปลกบางอย่างstatไม่ได้ติดตั้งบนกล่องและมันไม่น่าที่ฉันจะได้รับการติดตั้ง

ตัวเลือกอื่น ๆ ?

PS: gccไม่ได้ติดตั้งเช่นกัน


คุณสามารถอัปโหลดไบนารีที่คอมไพล์แล้วและรันที่นั่นได้หรือไม่?
imz - Ivan Zakharyaschev

@imz: ใช่นั่นเป็นอีกวิธีที่จะไป การfind -printfกระทำที่ดูเหมือนจะง่ายที่สุดแม้ว่า
alex

คำตอบ:


27

วิธีที่สั้นที่สุดของฉันใช้ zsh:

print -rl -- **/*(.Om)

(เพิ่มตัวระบุDวงกลมหากคุณต้องการแสดงรายการไฟล์ที่ซ่อนอยู่หรือไฟล์ในไดเรกทอรีที่ซ่อนอยู่)

หากคุณมี GNU ค้นหาให้พิมพ์เวลาแก้ไขไฟล์และเรียงลำดับตามนั้น ฉันถือว่าไม่มีบรรทัดใหม่ในชื่อไฟล์

find . -type f -printf '%T@ %p\n' | sort -k 1 -n | sed 's/^[^ ]* //'

หากคุณมี Perl (อีกครั้งสมมติว่าไม่มีบรรทัดใหม่ในชื่อไฟล์):

find . -type f -print |
perl -l -ne '
    $_{$_} = -M;  # store file age (mtime - now)
    END {
        $,="\n";
        print sort {$_{$b} <=> $_{$a}} keys %_;  # print by decreasing age
    }'

หากคุณมี Python (สมมติว่าไม่มีบรรทัดใหม่ในชื่อไฟล์):

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in sorted(times.iterkeys(), key=lambda f:times[f]): print f'

หากคุณมีการเข้าถึง SSH ไปยังเซิร์ฟเวอร์นั้นให้ติดตั้งไดเรกทอรีผ่านsshfsบนเครื่องที่ดีกว่า:

mkdir mnt
sshfs server:/path/to/directory mnt
zsh -c 'cd mnt && print -rl **/*(.Om)'
fusermount -u mnt

ด้วยเครื่องมือ POSIX เพียงอย่างเดียวมันมีความซับซ้อนมากขึ้นเนื่องจากไม่มีวิธีที่ดีในการค้นหาเวลาแก้ไขของไฟล์ วิธีมาตรฐานเพียงอย่างเดียวในการเรียกคืนเวลาของไฟล์คือlsและรูปแบบเอาต์พุตขึ้นอยู่กับโลแคลและยากต่อการแยกวิเคราะห์

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

set -ef                       # disable globbing
IFS='
'                             # split $(foo) only at newlines
set -- $(find . -type f)      # set positional arguments to the file names
mkdir links.tmp
cd links.tmp
i=0 list=
for f; do                     # hard link the files to links.tmp/0, links.tmp/1, …
  ln "../$f" $i
  i=$(($i+1))
done
set +f
for f in $(ls -t [0-9]*); do  # for each file, in reverse mtime order:
  eval 'list="${'$i'}         # prepend the file name to $list
$list"'
done
printf %s "$list"             # print the output
rm -f [0-9]*                  # clean up
cd ..
rmdir links.tmp

find . -print | xargs -n99999 -s999999 ls -ltrวิธีที่ง่ายที่สุดน่าจะเป็น แต่นั่นมีปัญหาที่ (1) xargsอาจไม่อนุญาตให้-mมากกว่า 512 หรือ-sมากกว่า 5120 และ (b) แม้ว่าคุณจะได้รับมันก็ยังมีขนาดสูงสุดที่เคอร์เนลกำหนดของรายการอาร์กิวเมนต์และสภาพแวดล้อมที่รวมกัน ความคิดส่วนใหญ่ของคุณ (บันทึก Perl และ Python) มีปัญหาเดียวกันซึ่งเป็นสาเหตุที่ฉันหลีกเลี่ยงการสร้างบรรทัดคำสั่งที่ยาวเป็นพิเศษ
geekosaur

โดยเฉพาะอย่างยิ่งฉันได้รับข้อผิดพลาด "รายการอาร์กิวเมนต์ยาวเกินไป" เป็นประจำโดยใช้zshglobs แบบเรียกซ้ำในกรณีทั่วไป
geekosaur

@geekosaur: เฉพาะกระบองที่น่ากลัวครั้งสุดท้ายเท่านั้นที่มีปัญหากับบรรทัดคำสั่งที่ยาว ใน zsh คุณสามารถทำมากกับ built-in (เช่นprint -rl **/*'s จำกัด เฉพาะเป็นเท่าใดฟรีหน่วยความจำที่คุณมี) zargsและเกินกว่าที่มี ข้อเสนอของคุณfind … | xargs … lsจะจัดเรียงอย่างถูกต้องหากxargsลงท้ายด้วยการเรียกใช้lsเพียงครั้งเดียวและจะไม่ทำงานหากมีอักขระพิเศษในชื่อไฟล์
Gilles 'หยุดความชั่วร้าย'

ขอบคุณมากสำหรับคำตอบอย่างละเอียดพร้อมตัวเลือกมากมาย! :)
alex

และนั่นคือเหตุผลที่ฉันรัก zsh
Profpatsch

14

สมมติว่า GNU find:

find . -printf '%T@ %c %p\n' | sort -k 1n,1 -k 7 | cut -d' ' -f2-

เปลี่ยน1n,1เป็น1nr,1หากคุณต้องการไฟล์ที่แสดงล่าสุดก่อน

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


จริงๆแล้วคุณสามารถเปลี่ยนรูปแบบวันที่และเวลาด้วยls --time-style="..."- ฉันไม่แน่ใจว่านี่เป็นแบบมาตรฐานหรือ GNU ls, GNU ที่เป็นไปได้
asoundmove

GNU อย่างแน่นอน
geekosaur

@asoundmove: ขออภัยกล่องเก่าเกินไป (RedHat 7.2) และlsไม่มีตัวเลือกนั้น
alex

7

ใน mac ไม่มีอาร์กิวเมนต์ -printf ที่จะค้นหา แต่คุณสามารถทำได้แทน:

find . -print0 | xargs -0 -n 100 stat -f"%m %Sm %N" | sort -n|awk '{$1="";print}'


0

อย่างใดอย่างหนึ่งสามารถลองนี้ (อย่างใดอย่างหนึ่งจะต้องสร้างมันเอง) https://github.com/shadkam/recentmost


6
ยินดีต้อนรับสู่ Unix & Linux Stack Exchange! ในขณะที่สิ่งนี้อาจตอบคำถามในทางทฤษฎีมันก็ควรที่จะรวมส่วนสำคัญของคำตอบที่นี่และให้ลิงค์สำหรับการอ้างอิง
slm

0

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

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

$ 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มากมายสามารถพบได้โดยไปที่ลิงก์


0

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

ด้วย findutils 4.6.0 ฉันชอบ:

find . -type f -mtime +270 -exec ls -laFGht --time-style=iso {} \+

คำสั่งดังกล่าวพบไฟล์ ( -type f) ในไดเรกทอรีการทำงานปัจจุบัน ( .) ที่มีการแก้ไขกว่า 270 วันที่ผ่านมา ( -mtime +270นอกจากนี้ยัง-mtime 0จะผลิตช่วง 24 ชั่วโมงและ-mtime -5แสดงให้เห็นว่าในช่วง 5 วัน) จากนั้นจะใช้lsเพื่อแสดงรายการตามวันที่ใหม่สุดก่อน ( -exec ls -laFGht --time-style=iso {} \+)

นี่คือตัวอย่างของการส่งออก:

-rwxrwx---+ 1 user1 208M 2018-07-16  ./filename.bak*
-rwxrwx---+ 1 user1  702 2018-07-15  ./filename.ldf*
-rwxrwx---+ 1 user1 208M 2018-07-15  ./filename.bak*

สิ่งที่ดีเกี่ยวกับเรื่องนี้คือเมื่อรายการได้รับการตรวจสอบแล้วมันเป็นเรื่องง่ายที่จะแทนที่ส่วนรายการด้วยfindคำสั่งลบ:

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