我有一个包含大量旧照片的文件夹,其中包含许多重复照片。手动排序需要很长时间,所以我想借此机会使用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}"
的示例。
答案 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
是最佳选择。它的优点是:
适用于文本和二进制文件,与diff
不同,仅适用于文本文件
在找到第一个差异后停止,因此非常有效
因此,您的代码可以写成:
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