2015-11-19 92 views
1

我想檢查最新的兩個文件是否不同。 這是我的代碼,它不起作用。如何比較最新的兩個文件是否相同或不相同?

#!/bin/bash 
set -x -e 

function test() { 
    ls ~/Downloads/* -t | head -n 2 | xargs cmp -s 
    echo $? 
} 

test 

謝謝。

+0

順便說一句,在'function'關鍵字使你的代碼與POSIX SH(與使用擴展實際增加值)不必要不相適應;考慮使用符合的語法'funcname(){...}'而不是'function funcname {...}'。 –

回答

1

假設你有GNU發現和GNU排序:

#!/bin/bash 
#  ^^^^ - not /bin/sh, which lacks <() 

{ 
    IFS= read -r -d '' file1 
    IFS= read -r -d '' file2 
} < <(find ~/Downloads -type f -mindepth 1 -maxdepth 1 -printf '%[email protected] %p\0' | sort -r -n -z) 

if cmp -s -- "$file1" "$file2"; then 
    echo "Files are identical" 
else 
    echo "Files differ" 
fi 

如果你的操作系統是MacOS X和你有GNU findutilscoreutils通過MacPortshomebrewfink安裝,你可能需要更換findgfindsortgsort獲得GNU而不是這些工具的BSD實現。這裏

要點:

  • find被要求發出在[epoch-timestamp] [filename][NULL]形式的流。這是因爲NUL是唯一不能存在於路徑名中的字符。
  • sort被要求以數字方式對此流進行排序。
  • 流的前兩項被讀入到shell變量中。
  • 在選項之後和位置參數前使用--參數cmp可確保文件名永遠不會被解析爲位置參數,即使開始於-

那麼,爲什麼不使用ls -t?考慮(作爲一個例子)如果你有一個用命令touch $'hello\nworld'創建的文件,在它的名字中有字面換行符,會發生什麼;取決於您的ls版本,它可能會作爲hello?world,hello^Mworldhello\nworld(在任何這些情況下,文件名如果視爲文字而不是全局展開的情況下實際不存在)或兩行(hello,和world。這會弄亂你的管道的其餘部分(和空格的文件名一樣簡單的事情也將打破xargs與默認選項,因爲將帶有文字引號的文件名; xargs是真正安全的,當與參數-0用於對待內容爲NUL-但與GNU擴展-d $'\n'一起使用時的默認值不太安全)。

參見:

相關問題