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!)


31

Làm cách nào tôi có thể nhận được danh sách tất cả các tệp trong thư mục hiện tại cùng với ngày sửa đổi của chúng và được sắp xếp theo ngày đó?

Bây giờ tôi biết làm thế nào để đạt được điều đó với find, statsort, nhưng vì một số lý do kỳ lạ, statnó không được cài đặt trên hộp và không chắc là tôi có thể cài đặt nó.

Còn lựa chọn nào khác không?

PS: gcckhông được cài đặt


Bạn có thể tải lên một nhị phân biên dịch và chạy nó ở đó?
imz - Ivan Zakharyaschev

@imz: vâng, đó là một cách khác để đi. Các find -printfhành động dường như là dễ dàng nhất mặc dù.
alex

Câu trả lời:


27

Phương pháp ngắn nhất của tôi sử dụng zsh:

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

(thêm Dvòng loại toàn cầu nếu bạn cũng muốn liệt kê các tệp bị ẩn hoặc các tệp trong các thư mục ẩn).

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 đó. Tôi giả sử không có dòng mới trong tên tập tin.

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

Nếu bạn có Perl (một lần nữa, giả sử 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";
        print sort {$_{$b} <=> $_{$a}} keys %_;  # print by decreasing age
    }'

Nếu bạn có Python (một lần nữa, giả sử không có dòng mới nào 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]): print f'

Nếu bạn có quyền truy cập SSH vào máy chủ đó, hãy gắn thư mục qua sshfs trên máy được trang bị tốt hơn:

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

Chỉ với các công cụ POSIX, nó phức tạp hơn nhiều, vì không có cách nào tốt để tìm thời gian sửa đổi của tệp. Cách tiêu chuẩn duy nhất để truy xuất thời gian của tệp là lsvà định dạng đầu ra phụ thuộc vào ngôn ngữ và khó phân tích.

Nếu bạn có thể ghi vào các tệp và bạn chỉ quan tâm đến các tệp thông thường và không có dòng mới nào trong tên tệp, thì đây là một loại bùn khủng khiếp: tạo liên kết cứng đến tất cả các tệp trong một thư mục và sắp xếp chúng theo thời gian sửa đổi.

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

Cách dễ nhất có lẽ là find . -print | xargs -n99999 -s999999 ls -ltr. Nhưng điều đó có một vấn đề là (1) xargscó thể không cho phép -mlớn hơn 512 hoặc -slớn hơn 5120 và (b) ngay cả khi bạn có thể khắc phục điều đó, vẫn có một kích thước tối đa áp dụng hạt nhân của danh sách và môi trường đối số kết hợp. Hầu hết các ý tưởng của bạn (lưu Perl và Python) đều có cùng một vấn đề, đó là lý do tại sao tôi đặc biệt tránh xây dựng các dòng lệnh dài.
geekizard

Cụ thể, tôi thường xuyên nhận được các lỗi "danh sách đối số quá dài" bằng cách sử dụng zshcác thuật toán đệ quy trong trường hợp chung.
geekizard

@geekizard: Chỉ có loại bùn khủng khiếp cuối cùng có vấn đề với các dòng lệnh dài. Trong zsh, bạn có thể làm được rất nhiều với các phần dựng sẵn (ví dụ: print -rl **/*giới hạn duy nhất là bạn có bao nhiêu bộ nhớ trống) và hơn thế nữa zargs. Đề xuất của find … | xargs … lsbạn sẽ sắp xếp chính xác nếu xargscuối cùng lschỉ gọi một lần và sẽ không hoạt động nếu có các ký tự đặc biệt trong tên tệp.
Gilles 'SO- ngừng trở nên xấu xa'

cảm ơn rất nhiều vì câu trả lời cực kỳ chi tiết với rất nhiều lựa chọn! :)
alex

Và đó là lý do tại sao tôi yêu zsh.
Profpatsch

14

Giả sử GNU find:

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

Thay đổi 1n,1thành 1nr,1nếu bạn muốn các tập tin được liệt kê gần đây nhất đầu tiên.

Nếu bạn không có GNU, findđiều đó trở nên khó khăn hơn vì lsđịnh dạng dấu thời gian của nó thay đổi rất nhiều (ví dụ, các tệp được sửa đổi có kiểu dấu thời gian khác nhau chẳng hạn).


Trên thực tế, bạn cũng có thể thay đổi định dạng ngày và giờ bằng ls --time-style="..."- Tôi không chắc đây là tiêu chuẩn hay GNU, có khả năng là GNU.
asoundmove

Chắc chắn là GNU.
geekizard

@asoundmove: thật không may, hộp quá cũ (RedHat 7.2) và lskhông có tùy chọn đó.
alex

7

Trên máy mac không có đối số -printf để tìm, nhưng bạn có thể làm điều này thay vào đó:

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



0

Bỏ qua các tập tin ẩn - với dấu thời gian đẹp và nhanh

Xử lý không gian trong tên tệp tốt - không phải là bạn nên sử dụng chúng!

$ 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

Nhiều findgalore có thể được tìm thấy bằng cách theo liên kết.


0

Nói chung về việc tìm kiếm các tập tin theo ngày (điều này sẽ không hoạt động cho poster gốc, nhưng tôi đã kết thúc ở đây vì vậy tôi nghĩ rằng những người khác cũng có thể). Trong trường hợp sử dụng của tôi, tôi muốn liệt kê các tệp cho mục đích xem xét chúng trước khi xóa.

Với findutils 4.6.0 tôi thích:

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

Lệnh trên tìm thấy các tệp ( -type f), trong thư mục làm việc hiện tại ( .) đã được sửa đổi hơn 270 ngày trước ( -mtime +270Cũng -mtime 0sẽ tạo ra 24 giờ qua và -mtime -5hiển thị 5 ngày qua). Sau đó, nó sử dụng lsđể liệt kê chúng theo ngày, mới nhất trước ( -exec ls -laFGht --time-style=iso {} \+)

Đây là một mẫu của đầu ra:

-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*

Điều tuyệt vời ở đây là một khi danh sách đã được xem xét, việc thay thế phần danh sách bằng findlệnh xóa là một vấn đề đơn giản .

find . -type f -mtime +270 -delete
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.