làm cách nào để kiểm tra xem tệp đã được tạo hơn x lần trước hay chưa?


106

Tôi muốn kiểm tra trong linux bash xem một tệp đã được tạo hơn x lần trước hay chưa.

giả sử tệp có tên là text.txt và thời gian là 2 giờ.

 if [ what? ]
 then
     echo "old enough"
 fi

Câu trả lời:


138

Chỉ dành cho thời gian sửa đổi

if test `find "text.txt" -mmin +120`
then
    echo old enough
fi

Bạn có thể sử dụng -cminđể thay đổi hoặc -amincho thời gian truy cập. Như những người khác đã chỉ ra, tôi không nghĩ rằng bạn có thể theo dõi thời gian tạo.


3
bạn có thể thả 'thử nghiệm' và các dấu gạch ngược. Điều này tương tự với 'if (test == true)' so với 'if (test)'
súng

2
Bạn hoàn toàn đúng; Tôi cho rằng tôi đã nghĩ rằng findtrả về khác 0 khi không tìm thấy kết quả phù hợp nào.
súng

4
Bạn có thể thả backticks và thực hiện nếu kiểm tra $ (tìm text.txt -mmin +120)
tommy.carstensen 14/1213

1
@BroSlow trông đẹp hơn: không thể có "nhiều hơn một". Tất nhiên, text.txtđược cho là không phải là một thư mục.
kmkaplan

2
Tôi thích cú pháp này hơn:[ "$(find path/to/file -mmin +120)" ] && echo "it is old"
Alfe

42

Tôi luôn thích sử dụng date -r /the/file +%sđể tìm tuổi của nó.

Bạn cũng có thể làm touch --date '2015-10-10 9:55' /tmp/fileđể có được thời gian cực kỳ chi tiết vào một ngày / giờ tùy ý.


Tôi đã tìm kiếm điều tương tự ngày hôm nay. Tốt!
Umair A.

Cảm ơn. Tôi đã đặt câu hỏi SO này vì tôi đã truy cập "cách in tuổi của tệp bash." Vì vậy, đây chính xác là những gì tôi đang tìm kiếm!
Noah Sussman

5
Cảm ơn! với cảnh báo duy nhất ở trên là dấu thời gian (không phải tuổi) nhưng có thể được sử dụng để xác định độ tuổi như vậy let AGE=$(($(date +%s)-$(date -r /path/to/file +%s))) [với giả định được tạo ra và không bao giờ sửa đổi, hoặc "độ tuổi liên quan đến mod"]
nhed

function file-age { FILE_CREATED_TIME=`date -r "$1" +%s`; TIME_NOW=`date +%s`; echo "$[ ${TIME_NOW} - ${FILE_CREATED_TIME} ]"; }
turiyag

1
@turiyag Lưu ý bắt buộc rằng $[ ], nếu không bị phản đối , ít nhất là cũ và ít di động hơn và nên sử dụng $(( ))thay thế; và backquotes mong manh hơn $( ); và các dấu gạch ngang trong tên hàm có thể không hoàn toàn di động. Bản chất của nó là tốt, mặc dù!
michaelb958 - GoFundMonica

23

Sử dụng statđể tìm ra ngày sửa đổi cuối cùng của tệp, dateđể tìm ra thời gian hiện tại và việc sử dụng cơ bản một cách tự do, người ta có thể thực hiện bài kiểm tra mà bạn muốn dựa trên thời gian sửa đổi cuối cùng của tệp 1 .

if [ "$(( $(date +"%s") - $(stat -c "%Y" $somefile) ))" -gt "7200" ]; then
   echo "$somefile is older then 2 hours"
fi

Mặc dù findcách tiếp cận này ít đọc được mã hơn một chút , nhưng tôi nghĩ rằng đó là một cách tiếp cận tốt hơn sau đó chạy findđể xem tệp bạn đã "tìm thấy". Ngoài ra, thao tác ngày tháng rất thú vị ;-)


  1. Như Phil đã lưu ý chính xác thời gian tạo không được ghi lại, nhưng sử dụng %Zthay vì %Ybên dưới để lấy "thời gian thay đổi" có thể là những gì bạn muốn.

[Cập nhật]

Đối với người dùng mac, hãy sử dụng stat -f "%m" $somefilethay vì cú pháp cụ thể của Linux ở trên


Ngày và chỉ số được xây dựng trong shell nào? Bash của tôi (GNU, 3.2.48) không có chúng.
Ian Clelland 09/09/09

ối xin lỗi. statkhông phải là bản dựng - rất tệ của tôi, tôi sẽ sửa.
Guss

1
@Guss giải pháp đúng là cài đặt coretutils với brew. :-)
Erik Johansson

1
@ErikJohansson Tôi không muốn yêu cầu cài đặt phần mềm bổ sung khi sử dụng phần mềm hiện có hoạt động tốt - đây không phải là Windows, bạn biết đấy ;-)
Guss

1
Đối với những người muốn sử dụng điều này nhưng sửa đổi nó, sẽ rất tốt nếu biết chính xác nó đang làm gì: $ (($ (ngày + "% s") - giây kể từ 1970-01-01 00:00:00 UTC (Epoch) $ (stat -c "% Y" $ somefile))) - Thời gian sửa đổi cuối cùng dưới dạng giây kể từ Epoch -gt "7200" - kiểm tra xem sự khác biệt có lớn hơn x số giây hay không.
sùng

16

Thời gian tạo không được lưu trữ.

Những gì được lưu trữ là ba dấu thời gian (nói chung, chúng có thể được tắt trên một số hệ thống tệp nhất định hoặc bằng các tùy chọn hệ thống tệp nhất định):

  • Lần truy cập cuối cùng
  • Lần sửa đổi cuối cùng
  • Lần thay đổi cuối cùng

"Thay đổi" đối với tệp được tính là thay đổi quyền, đổi tên, v.v. Trong khi sửa đổi chỉ là nội dung.


12

Mặc dù về mặt kỹ thuật, ctime không phải là thời điểm tạo ra, nhưng nó khá thường xuyên.

Vì ctime nó không bị ảnh hưởng bởi những thay đổi đối với nội dung của tệp, nó thường chỉ được cập nhật khi tệp được tạo. Và vâng - tôi có thể nghe thấy tất cả các bạn hét lên - nó cũng được cập nhật nếu bạn thay đổi quyền truy cập hoặc quyền sở hữu ... nhưng nói chung đó là điều được thực hiện một lần, thường là cùng lúc bạn đặt tệp ở đó.

Cá nhân tôi luôn sử dụng mtime cho mọi thứ, và tôi tưởng tượng đó là những gì bạn muốn. Nhưng dù sao đi nữa ... đây là một bản tóm tắt "không hấp dẫn" của Guss, trong một chức năng dễ sử dụng.

#! / bin / bash
function age () {
   tên tệp cục bộ = $ 1
   local change = `stat -c% Y" $ filename "`
   cục bộ bây giờ = `ngày +% s`
   địa phương đã trôi qua

   let elapsed = now-change
   echo $ trôi qua
}

tệp = "/"
echo Tuổi của $ file là $ (age "$ file") giây.

Điều này rất hữu ích, nhưng nó không hoạt động ngay lập tức cho OSX vì stat được triển khai khác nhau trên đó. Cách duy nhất tương thích giữa các hệ thống mà tôi tìm thấy là sử dụng perl. Tập lệnh sẽ hoạt động trên Mac nếu bạn thay thế dòng tương ứng bằng dòng này: local changed=$(perl -MFile::stat -e "print stat(\"${filename}\")->mtime") superuser.com/questions/427551/…
Bijou Trouvaille

1
"Thời gian sáng tạo" là một khái niệm khó nắm bắt. Nó có ý nghĩa gì đối với một tập tin được sao chép? Điều gì cho một tệp đã di chuyển? Điều gì sẽ xảy ra nếu nó được di chuyển qua một đường viền thiết bị (theo một nghĩa nào đó, nó đã được tạo mới)? Nó có ý nghĩa gì đối với một tệp được đóng gói và sau này không được đóng gói? Có thể có một số câu trả lời ở đây và không tồn tại sự đồng thuận. Mặc dù vậy, đề cập đến ctime là một điều tốt, nhưng tôi sẽ không đặt nó về mặt ngữ nghĩa với khái niệm mơ hồ về "thời gian sáng tạo". Đặc biệt là vì một đơn giản chmod, được áp dụng trên tệp, sẽ vô hiệu hóa ý tưởng đó. Nhưng tôi có thể sống cùng bạn khi làm điều đó ;-)
Alfe

@Alfe: Bạn đang bỏ lỡ +%shiệp hai
Grizly

Tuổi đó có thể ngắn hơn rất nhiều: age() { echo $(( $(date +%s) - $(date -r "$1" +%s) )); } (Cảm ơn @Grizly đã chỉnh sửa!)
Alfe

Trên thực tế, tốt hơn là sử dụng thời gian truy cập là thời gian tạo trên tất cả các hệ thống tệp được gắn với noatimetùy chọn (điều này tốt cho hiệu suất, vì vậy bạn nên sử dụng nó). Vì vậy, chỉ cần sử dụng %Xthay vì %Y.
Nux

7

Tìm một cái là tốt nhưng tôi nghĩ bạn có thể sử dụng cách khác, đặc biệt là nếu bạn cần bao nhiêu giây để tệp cũ

date -d "now - $( stat -c "%Y" $filename ) seconds" +%s

sử dụng ngày GNU


sử dụng gstat, "brew install coreutils"
Erik Johansson

3

Xem xét kết quả của 'chỉ số' công cụ:

  File: `infolog.txt'
  Size: 694         Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d  Inode: 11635578    Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/     fdr)   Gid: ( 1000/     fdr)
Access: 2009-01-01 22:04:15.000000000 -0800
Modify: 2009-01-01 22:05:05.000000000 -0800
Change: 2009-01-01 22:05:05.000000000 -0800

Bạn có thể thấy ở đây ba ngày để Truy cập / sửa đổi / thay đổi. Không có ngày tạo. Bạn chỉ có thể thực sự chắc chắn khi nội dung tệp đã được sửa đổi (trường "sửa đổi") hoặc inode của nó đã thay đổi (trường "thay đổi").

Ví dụ về thời điểm cả hai trường được cập nhật:

"Sửa đổi" sẽ được cập nhật nếu ai đó nối thông tin bổ sung vào cuối tệp.

"Thay đổi" sẽ được cập nhật nếu ai đó thay đổi quyền qua chmod.


được cấp, thống kê có thể cho bạn biết thông tin liên quan. Nhưng sẽ khá tẻ nhạt khi phân tích cú pháp để có được những gì chúng ta muốn.
PypeBros

0

tôi sử dụng

file_age() {
    local filename=$1
    echo $(( $(date +%s) - $(date -r $filename +%s) ))
}

is_stale() {
    local filename=$1
    local max_minutes=20
    [ $(file_age $filename) -gt $(( $max_minutes*60 )) ]
}

if is_stale /my/file; then
    ...
fi
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.