使用带有输出重定向的cmp,bash shell脚本无法正常工作

gc5*_*gc5 0 bash cmp stderr io-redirection output

我正在尝试编写一个bash脚本,从文件夹中删除重复的文件,只保留一个副本.该脚本如下:

#!/bin/sh

for f1 in `find ./ -name "*.txt"`
do
    if test -f $f1
    then
        for f2 in `find ./ -name "*.txt"`
        do
            if [ -f $f2 ] && [ "$f1" != "$f2" ]
            then
                # if cmp $f1 $f2 &> /dev/null # DOES NOT WORK
                if cmp $f1 $f2
                then
                    rm $f2
                    echo "$f2 purged"
                fi 
            fi
        done
    fi 
done 
Run Code Online (Sandbox Code Playgroud)

我想重定向输出和stderr以/dev/null避免将它们打印到屏幕..但使用注释语句此脚本不能按预期工作并删除所有文件,但第一个..

如果需要,我会提供更多信息.

谢谢

kob*_*ame 8

几条评论:

一,:

for f1 in `find ./ -name "*.txt"`
do
    if test -f $f1
    then
Run Code Online (Sandbox Code Playgroud)

与(仅查找txt扩展名为普通文件)相同

for f1 in `find ./ -type f -name "*.txt"`
Run Code Online (Sandbox Code Playgroud)

更好的语法(仅限bash)是

for f1 in $(find ./ -type f -name "*.txt")
Run Code Online (Sandbox Code Playgroud)

最后整体是错误的,因为如果文件名包含空格,f1变量将不会获得完整的路径名.所以相反for做:

find ./ -type f -name "*.txt" -print | while read -r f1
Run Code Online (Sandbox Code Playgroud)

正如@Sir Athos指出的那样,文件名可以包含,\n所以最好使用

find . -type f -name "*.txt" -print0 | while IFS= read -r -d '' f1
Run Code Online (Sandbox Code Playgroud)

第二:

使用"$f1"而不是$f1- 再次,因为$f1可以包含空格.

第三:

进行N*N比较并不是很有效.你应该为每个txt文件做一个校验和(md5或更好的sha256).校验和相同时 - 文件是重复的.

如果您不信任校验和,则只需比较具有相同校验和的文件.具有不同校验和的文件确实不重复.;)

制作校验和很慢,所以你应该首先将ony文件与same size.不同大小的文件不重复...

你可以跳过空txt files- 它们都是重复的:).

所以最后的命令可以是:

find -not -empty -type f -name \*.txt -printf "%s\n" | sort -rn | uniq -d |\
xargs -I% -n1 find -type f -name \*.txt -size %c -print0 | xargs -0 md5sum |\
sort | uniq -w32 --all-repeated=separate
Run Code Online (Sandbox Code Playgroud)

评论说:

#find all non-empty file with the txt extension and print their size (in bytes)
find . -not -empty -type f -name \*.txt -printf "%s\n" |\

#sort the sizes numerically, and keep only duplicated sizes
sort -rn | uniq -d |\

#for each sizes (what are duplicated) find all files with the given size and print their name (path)
xargs -I% -n1 find . -type f -name \*.txt -size %c -print0 |\

#make an md5 checksum for them
xargs -0 md5sum |\

#sort the checksums and keep duplicated files separated with an empty line
sort | uniq -w32 --all-repeated=separate
Run Code Online (Sandbox Code Playgroud)

现在输出,您可以简单地编辑输出文件并决定要删除的内容以及要保留的文件.