2015-11-19 59 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'一起使用时的默认值不太安全)。

参见:

相关问题