比較兩個文件修改日期
我正在創建一個通用編譯/轉譯系統。了解文件是否已經編譯/轉譯的一種方法是比較源文件和目標文件的修改日期。
我需要編寫一個可以做到這一點的 bash 腳本:
source_file=foo; target_file=bar; stat_source=$(stat source_file); stat_target=$(stat target_file);
但是如何從 stat 輸出中提取日期並進行比較?有沒有比
stat
比較文件的最近修改時間更好的方法?如果我在日誌文件上呼叫 stat ,我會得到:
16777220 12391188 -rw-r--r-- 1 alexamil staff 0 321 "Jun 22 17:45:53 2017" "Jun 22 17:20:51 2017" "Jun 22 17:20:51 2017" "Jun 22 15:40:19 2017" 4096 8 0 test.log
AFAICT,時間粒度不小於秒。如果可能的話,我需要得到比這更細化的東西。
在這個linux系統上測試。測試文件時間的常用方法是 shell:
[ file1 -nt file2 ] && echo "yes"
似乎與秒一起工作。這將接觸時間差小於一秒的文件,但不會檢測到該差異:
$ touch file2; sleep 0.1; touch file1; [ file1 -nt file2 ] && echo "yes"
確認問題(點後的時間為納秒):
$ ls --time-style=full-iso -l file? -rw-r--r-- 1 user user 0 2017-06-23 01:37:01.707387495 -0400 file1 -rw-r--r-- 1 user user 0 2017-06-23 01:37:01.599392538 -0400 file2
比
file1
(有點)新file2
。現在的問題將是正確處理時間值。
一種解決方案是使用 ls 的格式化輸出:
$ ls --time-style=+%s.%N -l file? -rw-r--r-- 1 user user 0 1498196221.707387495 file1 -rw-r--r-- 1 user user 0 1498196221.599392538 file2
將時間提取到兩個變數(不帶點):
$ file1time=$(ls --time-style=+%s%N -l file1 | awk "{print(\$6)}") $ file2time=$(ls --time-style=+%s%N -l file2 | awk "{print(\$6)}")
並比較時間(納秒的時間幾乎不適合 64 位值。如果您的系統不使用 64 位,則此比較將失敗):
$ [ $file1time -gt $file2time ] && echo "yes" yes
這表明它
file1
比file2
如果
ls
無法獲得所需的格式,那麼您可以嘗試 stat.$ stat file1 File: file1 Size: 0 Blocks: 0 IO Block: 4096 regular file Device: 805h/2053d Inode: 9180838 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 1000/ user) Gid: ( 1000/ user) Access: 2017-06-23 01:37:01.707387495 -0400 Modify: 2017-06-23 01:37:01.707387495 -0400 Change: 2017-06-23 01:37:01.707387495 -0400 Birth: -
如果輸出顯示納秒,我們將需要日期來解析(和格式化)時間。
$ stat --printf='%y\n' file1 2017-06-23 01:37:01.707387495 -0400 $ date +'%s%N' -d "$(stat --printf='%y\n' file1)" 1498196221707387495
其餘的都是一樣的,把file1和file2的結果賦值給兩個變數,數值比較。
鑑於您使用的是**
stat
**(類似的功能,但在 BSD 和 GNU 上的輸出格式不同),您還可以使用該test
實用程序,它直接進行此比較:FILE1 -nt FILE2 FILE1 is newer (modification date) than FILE2 FILE1 -ot FILE2 FILE1 is older than FILE2
在你的例子中,
if [ "$source_file" -nt "$target_file" ] then printf '%s\n' "$source_file is newer than $target_file" fi
該功能在 POSIX 中不可用(請參閱其文件
test
),它提供了一個基本原理:一些新發明的或來自 KornShell 的額外初選作為條件命令的一部分出現在早期提案中(
$$ [ $$]):s1
>
s2、s1<
s2、str = 模式、str != 模式、f1 **-nt
**f2、f1 **-ot
**f2 和 f1 -ef f2。當從 shell 中刪除條件命令時,它們沒有被帶到測試實用程序中,因為它們沒有包含在 sh 實用程序的歷史實現中內置的測試實用程序中。不過,隨著該功能得到廣泛支持,這種情況在未來可能會發生變化。
請注意,當操作數是符號連結時,考慮的是符號連結目標的修改時間(這通常是您想要的,
find -newer
如果不是,則使用)。當符號連結無法解析時,實現之間的行為(有些人認為現有文件總是比無法解析的文件更新,如果任何操作數無法解析,有些人總是會報告錯誤)。另請注意,並非所有實現都支持亞秒級粒度(
bash
’stest
/[
builtin 從 4.4 版開始仍然不支持,例如,GNUtest
和test
內置的zsh
orksh93
至少在 GNU/Linux 上)。以供參考: