用于比较文件的Bash脚本

时间:2017-01-01 02:20:49

标签: bash sorting

我有一个包含大量旧照片的文件夹,其中包含许多重复照片。手动排序需要很长时间,所以我想借此机会使用bash。

现在我有了代码:

#!/bin/bash

directory="~/Desktop/Test/*"
for file in ${directory};
do
    for filex in ${directory}:
    do
        if [ $( diff {$file} {$filex} ) == 0 ]
        then
            mv ${filex} ~/Desktop
            break
        fi
    done
done 

获取退出代码:

diff: {~/Desktop/Test/*}: No such file or directory
diff: {~/Desktop/Test/*:}: No such file or directory
File_compare: line 8: [: ==: unary operator expected

我已经尝试修改我在网上找到的工作代码,但似乎总是吐出一些像这样的错误。我猜这是嵌套for循环的问题?

另外,为什么看起来有不同的方法来调用变量?我见过使用${file}, "$file", and "${file}"的示例。

4 个答案:

答案 0 :(得分:6)

你有{}在错误的地方:

if [ $( diff {$file} {$filex} ) == 0 ]

他们应该在:

if [ $( diff ${file} ${filex} ) == 0 ]

(虽然大括号现在是可选的),但你应该在文件名中留出空格:

if [ $( diff "${file}" "${filex}" ) == 0 ]

现在它根本无法正常工作,因为当diff没有发现任何差异时,它不会产生任何输出(并且您会收到错误,因为==运算符在其左侧并不期望任何内容) 。您可以通过双引$(…)if [ "$( diff … )" == "" ])的值来修复它,但您应该直接测试diff的退出状态:

if diff "${file}" "${filex}"
then : no difference
else : there is a difference
fi

并且可能用于比较图像,您应该使用cmp(在静音模式下)而不是diff

if cmp -s "$file" "$filex"
then : no difference
else : there is a difference
fi

答案 1 :(得分:4)

除了Jonathan Leffler指出的问题之外:

directory="~/Desktop/Test/*"
for file in ${directory};

~*不会在双引号内扩展;当你使用没有引号的变量时,*会被扩展,但由于~不会,它会在实际名为“〜”的目录下查找文件(不是你的主目录),它将找不到任何匹配项。此外,正如Jonathan指出的那样,使用不带双引号的变量(如${directory})将使您遇到包含空格或其他元字符的文件名时出现问题。更好的方法是不将通配符放在变量中,在引用变量时使用它,变量用双引号和*在它们之外:

directory=~/"Desktop/Test"
for file in "${directory}"/*;

哦,另外注意:在脚本中使用mv时,最好使用mv -i以避免意外覆盖同名的其他文件。

并且:使用shellcheck.net来检查您的代码并指出常见错误。

答案 2 :(得分:3)

如果您只是想知道两个文件是否不同,cmp是最佳选择。它的优点是:

  1. 适用于文本和二进制文件,与diff不同,仅适用于文本文件

  2. 在找到第一个差异后停止,因此非常有效

  3. 因此,您的代码可以写成:

    if ! cmp -s "$file" "$filex"; then
      # files differ...
      mv "$filex" ~/Desktop
    
      # any other logic here
    fi
    

    希望这会有所帮助。我不明白你要对你的循环做什么,因此没有写完整的代码。

答案 3 :(得分:1)

您可以使用diff "$file" "$filex" &>/dev/null并使用$?获取最后一个命令结果:

#!/bin/bash

SEARCH_DIR="."
DEST_DIR="./result"

mkdir -p "$DEST_DIR"

directory="."

ls $directory | while read file;
do
    ls $directory | while read filex;
    do
        if [ ! -d "$filex" ] && [ ! -d "$file" ] && [ "$filex" != "$file" ];
        then

            diff "$file" "$filex" &>/dev/null

            if [ "$?" == 0 ];
            then
                echo "$filex is a duplicate. Copying to $DEST_DIR"
                mv "$filex" "$DEST_DIR"
            fi
        fi
    done
done 

请注意,您还可以使用fslintfdupes实用程序查找重复项