Unix / Linux tìm và sắp xếp theo ngày sửa đổi


131

Làm thế nào tôi có thể làm một đơn giản findđể sắp xếp các kết quả bằng cách sửa đổi gần đây nhất?

Đây là hiện tại findtôi đang sử dụng (Tôi đang thực hiện thoát shell trong PHP, vì vậy đó là lý do cho các biến):

find '$dir' -name '$str'\* -print | head -10

Làm thế nào tôi có thể có thứ tự này tìm kiếm bằng cách sửa đổi gần đây nhất? (Lưu ý tôi không muốn nó sắp xếp 'sau' tìm kiếm, mà là tìm kết quả dựa trên những gì được sửa đổi gần đây nhất.)


github.com/shadkam/recentest sẽ làm những gì mong muốn - nhưng người ta cần xây dựng nó
user3392225

Câu trả lời:


145

Dùng cái này:

find . -printf "%T@ %Tc %p\n" | sort -n

printfđối số từ man find:

  • %Tk: Thời gian sửa đổi lần cuối của tệp theo định dạng được chỉ định bởi k.

  • @: giây kể từ ngày 1 tháng 1 năm 1970, 00:00 GMT, với phần phân đoạn.

  • c: ngày và giờ của địa phương (Thứ bảy 04 tháng 12 12:02:33 EST 1989).

  • %p: Tên tệp.


5
+1 Rất hữu ích, câu trả lời đầu tiên cho điều này tôi đã tìm thấy với đầu ra ngày có thể đọc / hữu ích
Jake N

đáng tin cậy nhất (và rất đơn giản) vì thời gian được cấp là tuần tự số (do đó luôn luôn được sắp xếp hợp lý), thx!
Sức mạnh Bảo Bình

1
Tôi có bí danh này để tìm các tệp gần đây trong phần của mình ~/.zshrc: fr () { find ./ -iname "*"$@"*" -printf "%T@ %Td-%Tb-%TY %Tk:%TM %p\n" | sort -n | cut -d " " -f 2- | grep -i "$@" ; }Nó đệ quy tìm tất cả các tệp có chứa mẫu của đối số đầu tiên được truyền cho lệnh ( fr <pattern>) và sắp xếp chúng với tệp gần nhất cuối cùng.
joelostblom

Điều đó thật tuyệt !!! Để sử dụng với symlink, hãy sử dụngfind -L ...
Varun Chandak

1
Bạn có thể muốn sử dụng ssedđể thoát khỏi phần phân đoạn giây và vẫn sử dụng ISO8601 như @PeterMortensen đã trình bày:find . -type f -printf "%TY-%Tm-%TdT%TT %p\n" | sort -r | ssed -R 's/^([^.]+)\.\d+ (.*)$/\1 \2/'
Ludovic Kuty

81

Phương pháp đơn giản nhất là sử dụng zsh, nhờ vào vòng loại toàn cầu của nó .

print -lr -- $dir/**/$str*(om[1,10])

Nếu bạn có GNU find, hãy làm cho nó in thời gian sửa đổi tệp và sắp xếp theo đó.

find -type f -printf '%T@ %p\0' |
sort -zk 1nr |
sed -z 's/^[^ ]* //' | tr '\0' '\n' | head -n 10

Nếu bạn có GNU tìm nhưng không phải các tiện ích GNU khác, hãy sử dụng các dòng mới làm dấu phân cách thay vì null; bạn sẽ mất hỗ trợ cho tên tệp có chứa dòng mới.

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

Nếu bạn có Perl (ở đây tôi sẽ cho rằng không có dòng mới nào trong tên tệp):

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

Nếu bạn có Python (cũng giả sử không có dòng mới trong tên tệp):

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], reverse=True))[:10]: print f'

Có lẽ có một cách để làm điều tương tự trong PHP, nhưng tôi không biết điều đó.

Nếu bạn chỉ muốn làm việc với các công cụ POSIX, thì nó khá phức tạp; xem Cách liệt kê các tệp được sắp xếp theo ngày sửa đổi theo cách đệ quy (không có lệnh stat nào có sẵn!) (truy xuất lại 10 đầu tiên là phần dễ dàng).


Tôi nghĩ rằng findphiên bản hiển thị các tệp cũ nhất và bạn cần thêm -rtùy chọn này sort.
Quentin Pradet

Sed của tôi nói rằng nó không có tùy chọn -z.
Kef Schecter

@KefSchecter Sau đó, sử dụng dòng mới làm dấu phân cách, nhưng bạn sẽ mất hỗ trợ cho dòng mới trong tên tệp.
Gilles

Trên đây là cho python2. Nếu bạn chỉ có python3, một số thay đổi nhỏ: python3 -c 'nhập os, sys; lần = {} cho f trong sys.stdin.readlines (): f = f [0: -1]; times [f] = os.stat (f) .st_mtime cho f in (sort (times.keys (), key = lambda f: times [f], Reverse = True)) [: 10]: print (f); '
Neil McGill

40

Bạn không cần PHP hay Python, chỉ cần ls :

man ls:
-t     sort by modification time
-r,    reverse order while sorting (--reverse )
-1     list one file per line

find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;

Nếu lệnh * thoát với trạng thái lỗi (ví dụ: Danh sách đối số quá dài ), thì bạn có thể lặp lại với find. Paraphrased from: Độ dài tối đa của các đối số cho một quy trình mới

  • find . -print0|xargs -0 command (tối ưu hóa tốc độ, nếu tìm thấy không thực hiện "-exec +" nhưng biết "-print0")
  • find . -print|xargs command (nếu không có khoảng trắng trong các đối số)

Nếu phần chính của các đối số bao gồm các đường dẫn dài, tuyệt đối hoặc tương đối, thì hãy thử chuyển hành động của bạn vào thư mục: cd /directory/with/long/path; command *Và một cách khắc phục nhanh khác có thể là khớp với ít đối số hơn:command [a-e]*; command [f-m]*; ...


1
Nếu có nhiều tệp, điều này không thành công với 'Danh sách đối số quá dài' trên ls.
thỉnh thoảng

1
Đó là sự thật, nhưng tôi tin rằng các câu hỏi là "làm thế nào để tôi làm một cách đơn giản tìm thấy ..."
Ярослав Рахматуллин

2
Tôi không thể trích dẫn tên tệp theo cách xargs có thể hiểu (không có tùy chọn -0 và các kiểu trích dẫn khác nhau là không đủ)
Tobu

10

Bạn chỉ cần ls

Bạn có thể làm find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;như đã nêu ở trên,

hoặc là

ls -1rt `find /wherever/your/file/hides -type f`

2
Nếu có nhiều tệp, điều này không thành công với 'Danh sách đối số quá dài' trên ls. Có lẽ recook để sử dụng xargs?
thỉnh thoảng

2
Nhưng nếu xargsgọi lsnhiều lần, sắp xếp sẽ bị hỏng.
Aaron D. Marasco

Điều này không thành công cho các tập tin với không gian trong tên của họ. Có lời khuyên nào không?
dùng74094

Chỉ cần vấp phải câu trả lời này và đó chính xác là những gì tôi cần trong một tình huống tương tự. Câu hỏi: +;cuối cùng làm gì? Nó dường như cho kết quả tương tự mà không có ;tuy nhiên nó không hoạt động mà không có +?
RocketNuts

Điều này cũng giống như một câu trả lời khác được đăng 8 tháng trước, ngoại trừ phần về việc sử dụng "ls -1rt` find", bị hỏng
Clément

7

Mở rộng câu trả lời của người dùng 195696 :

find . -type f -printf "%T@\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-

Đối với mỗi tệp, lần đầu tiên này xuất ra dấu thời gian số (để sắp xếp theo, theo bảng \t, sau đó là dấu thời gian có thể đọc được của con người, sau đó kích thước tệp (không may find-printfkhông thể thực hiện trong mebibytes, chỉ kibibytes), sau đó là tên tệp với họ hàng con đường.

Sau đó sort -nsắp xếp nó theo trường số đầu tiên.

Sau đó cutthoát khỏi trường số đầu tiên mà người dùng không quan tâm. (In trường thứ hai trở đi.) Dấu tách trường mặc định là \thoặc lập bảng.

Ví dụ về đầu ra:

Thu 06 Feb 2014 04:49:14 PM EST     64 KiB ./057_h2_f7_10/h2_f7_10.class
Fri 07 Feb 2014 02:08:30 AM EST 7962976 KiB ./056_h2_f7_400/h2__rh_4e-4.mph
Fri 07 Feb 2014 02:23:24 AM EST 7962976 KiB ./056_h2_f7_400/h2_f7_400_out_Model.mph
Fri 07 Feb 2014 02:23:24 AM EST      0 KiB ./056_h2_f7_400/h2_f7_400_out.mph.status
Fri 07 Feb 2014 02:23:24 AM EST     64 KiB ./056_h2_f7_400/1579678.out
Fri 07 Feb 2014 03:47:31 AM EST 8132224 KiB ./057_h2_f7_10/h2__rh_1e-5.mph
Fri 07 Feb 2014 04:00:49 AM EST 8132224 KiB ./057_h2_f7_10/h2_f7_10_out_Model.mph
Fri 07 Feb 2014 04:00:49 AM EST      0 KiB ./057_h2_f7_10/h2_f7_10_out.mph.status
Fri 07 Feb 2014 04:00:49 AM EST     64 KiB ./057_h2_f7_10/1579679.out
Fri 07 Feb 2014 09:47:18 AM EST   9280 KiB ./056_h2_f7_400/h2__rh_4e-4.mat
Fri 07 Feb 2014 10:51:23 AM EST   9728 KiB ./018_bidomain/h2_plain__rh_1e-5.mat
Fri 07 Feb 2014 10:58:33 AM EST   9568 KiB ./057_h2_f7_10/h2__rh_1e-5.mat
Fri 07 Feb 2014 05:05:38 PM EST     64 KiB ./058_h2_f7_stationary/h2_f7_stationary.java
Fri 07 Feb 2014 06:06:29 PM EST     32 KiB ./058_h2_f7_stationary/slurm.slurm
Sat 08 Feb 2014 03:42:07 AM EST      0 KiB ./058_h2_f7_stationary/1581061.err
Sat 08 Feb 2014 03:42:14 AM EST     64 KiB ./058_h2_f7_stationary/h2_f7_stationary.class
Sat 08 Feb 2014 03:58:28 AM EST  70016 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mph
Sat 08 Feb 2014 04:12:40 AM EST  70304 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mph
Sat 08 Feb 2014 04:12:53 AM EST  70304 KiB ./058_h2_f7_stationary/h2_f7_stationary_out_Model.mph
Sat 08 Feb 2014 04:12:53 AM EST      0 KiB ./058_h2_f7_stationary/h2_f7_stationary_out.mph.status
Sat 08 Feb 2014 04:12:53 AM EST     32 KiB ./058_h2_f7_stationary/1581061.out
Mon 10 Feb 2014 11:40:54 AM EST    224 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mat
Mon 10 Feb 2014 11:42:32 AM EST    224 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mat
Mon 10 Feb 2014 11:50:08 AM EST     32 KiB ./plot_grid.m

Tôi cố tình tạo ra các ký tự trường kích thước 6 ký tự, bởi vì nếu làm cho nó dài hơn, sẽ khó phân biệt trực quan các tệp lớn như thế nào. Bằng cách này, các tệp lớn hơn 1e6 KiB bị tắt: bởi 1 char có nghĩa là 1-9 GB, bởi 2 ký tự có nghĩa là 10-99 GB, v.v.


Chỉnh sửa: đây là một phiên bản khác (kể từ khi find . -printf "%Tc"gặp sự cố trên MinGW / MSYS):

find . -type f -printf "%T@\t%p\n" | sort -n | cut -f 2- | xargs -I{} ls -Glath --si {}

Cho đầu ra như:

-rw-r--r-- 1 es 23K Jul 10  2010 ./laptop_0000071.jpg
-rw-r--r-- 1 es 43M Jul 29 19:19 ./work.xcf
-rw-r--r-- 1 es 87K Jul 29 20:11 ./patent_lamps/US Patent 274427 Maxim Lamp Holder.jpg
-rw-r--r-- 1 es 151K Jul 29 20:12 ./patent_lamps/Edison screw-in socket.png
-rw-r--r-- 1 es 50K Jul 29 20:13 ./patent_lamps/1157 Lamp.jpg
-rw-r--r-- 1 es 38K Jul 29 20:14 ./patent_lamps/US06919684-20050719-D00001.png

Ở đâu:

  • -I{}khiến sự xuất hiện của {}được thay thế bằng một đối số và các dòng mới hiện là dấu phân cách đối số (lưu ý các khoảng trắng trong tên tệp ở trên).

  • ls -G ngăn chặn việc in tên nhóm (lãng phí không gian).

  • ls -h --sitạo kích thước tập tin con người có thể đọc được (chính xác hơn với --si).

  • ls -t sắp xếp theo thời gian, không liên quan ở đây, nhưng đó là những gì tôi thường sử dụng.


1
Lưu ý: để sắp xếp theo kích thước tệp thay vào đó, chỉ cần thay thế T@bằng smột trong các lệnh trên.
Evgeni Sergeev

3

Biến thể OS X của câu trả lời của @ user195696:

  1. Với dấu thời gian:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r
    
  2. Không có dấu thời gian:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r | awk -F' ' '{ print substr($0, length($1) + 2) }'
    

1

Tôi thấy rằng điều này hoàn thành công việc trên Mac OS X (và đủ chung để hoạt động trên các Unixen khác):

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort

2
Đáng buồn thay, điều này in ra tên tháng được bản địa hóa trên thiết lập Croatia của tôi, làm cho sắp xếp không chính xác.
Ivan Vučica

câu trả lời của người dùng 195696 hoạt động cho thiết lập Croatia (và những người khác).
Peter Mortensen

1

Nếu findlựa chọn của bạn rất đơn giản, bạn có thể thực hiện mà không cần nó và chỉ cần sử dụng ls:

ls -1 *.cc # -r -t optional

1

Thử:

find '$dir' -name '$str'\* -print | xargs ls -tl | head -10

Nhưng nó cũng hữu ích để lọc dữ liệu theo -mmin/ -mtime-type.


1

Sử dụng:

find . -type f -mtime 0 -printf "[%TD %TI:%TM%Tp] %s %p\n" | sort -n | awk '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';

Lệnh này sẽ sắp xếp các tệp theo ngày sửa đổi.

Và hiển thị như:

[12/05/13 03:10PM] 1.75 MB ./file.text
[12/06/13 11:52PM] 2.90 MB ./file2.mp4
[12/07/13 04:11PM] 4.88 MB ./file3.mp4
[12/07/13 09:17PM] 4.74 MB ./test.apk

Tôi đã cải thiện chuỗi này để xử lý khoảng trắng trong tên tệp, xem superuser.com/a/777007/134532
jan

1

Tôi có một giải pháp đơn giản hoạt động cho cả FreeBSD (OS X) và Linux:

find . -type f -exec ls -t {} +

Điều này hoạt động hoàn hảo - nên được trả lời chính xác, hoặc ít nhất là đánh giá cao hơn!
Digitaltoast

0

Tôi không nghĩ findcó bất kỳ tùy chọn nào để sửa đổi thứ tự đầu ra. -mtime-mminsẽ cho phép bạn giới hạn kết quả đối với các tệp đã được sửa đổi trong một cửa sổ thời gian nhất định, nhưng đầu ra sẽ không được sắp xếp - bạn sẽ phải tự làm điều đó. GNU findcó một -printftùy chọn, trong số những thứ khác, sẽ cho phép bạn in thời gian sửa đổi của từng tệp được tìm thấy (chuỗi định dạng %thoặc %Tk); điều đó có thể giúp bạn sắp xếp findđầu ra theo cách bạn muốn.


0

Tôi đã cải thiện câu trả lời của Akashs bằng cách tạo khoảng trắng xử lý tập lệnh trong tên tệp chính xác:

find . -type f -mtime 0 -printf ";[%TD %TI:%TM%Tp];%s;%p\n" | sort -n | awk -F ";" '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';

0

Nếu bạn muốn đặt hàng tất cả các tệp PNG theo thời gian trong $PWD:

Điều này đơn giản cho tất cả sự linh hoạt của regrec trên findvà trên ls.

find $PWD -name "*.png" -print0 | xargs -0 ls -laht | less

0

Bạn có thể sử dụng stattrên BSD và Linux (không phải trên POSIX) theo cách này:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | cut -f2-

Nếu bạn muốn giới hạn số lượng:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | head -[the number] | cut -f2-

-1

Nếu bạn chỉ muốn có được một đường dẫn đầy đủ của từng mục, bạn có thể viết ra như thế này.

 find FIND_ROOT -maxdepth 1 -type f -printf "%T@ %p\n" | sort -nr | head -10 | cut -d ' ' -f 2

Trong đó
-printf "% T @% p \ n" để đưa ra tiêu chí sắp xếp (ngày),
'sort -nr' để sắp xếp theo ngày,
đầu -10 để liệt kê 10 kết quả hàng đầu,
cắt -d '' -f 2 để cắt dấu thời gian hàng đầu trên mỗi dòng.


-3

Tôi có một giải pháp đơn giản.

Sau khi cdvào một thư mục, sử dụng

find . -iname "*" -ls


1
Điều này không sắp xếp theo ngày sửa đổi.
DavidPostill
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.