根据文件名过滤图片,为什么?

根据文件名过滤图片,为什么?

使用下面的代码过滤图像时,我还需要过滤文件。

例如,IMG_0079.JPG.JPG,当运行下面的代码时,它允许.JPG过滤掉附加的文件,我似乎无法发现为什么?

  • 检查输入是否正确

    if [ $# != 2 ]; then
       echo "Usage: phar image_path archive_path" && exit;
    fi
    
  • 如果目标目录不存在,这将创建一个

    mkdir -p $2
    
  • 查找、复制并向文件添加必要后缀的语句

    find $1 -iname IMG_[0-9][0-9][0-9][0-9].JPG -exec cp -b --suffix=.JPG 
    {} $2 \; 
    echo complete!
    
  • 检查并删除重复的语句。它将比较每个文件的 md5。

        shopt -s nullglob              
        for file in "$2"/* 
        do
          md5sum=$(md5sum < "$file")        
          echo "-- Found: $file ($md5sum)"
          for duplicate in "$2"/*     #loop to find/remove duplicates
          do
            [ "$file" = "$duplicate" ] && continue      
            #comparison of 2 files
            [ "$md5sum" = "$(md5sum < "$duplicate")" ] && rm -v             
            "$duplicate"     
            #removal of duplicates
          done
        done
    

答案1

如果我理解正确的话,你的问题就在于此:

find $1 -iname IMG_[0-9][0-9][0-9][0-9].JPG

.JPG.JPG从一开始就找不到文件。看:

mkdir JPG
for n in 9 8 7 6 5 4 3 2 1
    do touch ./JPG/IMG_000${n}.JPG
done
find ./JPG -iname IMG_[0-9][0-9][0-9][0-9].JPG

###OUTPUT###

./JPG/IMG_0001.JPG
./JPG/IMG_0002.JPG
./JPG/IMG_0003.JPG
./JPG/IMG_0004.JPG
./JPG/IMG_0005.JPG
./JPG/IMG_0006.JPG
./JPG/IMG_0007.JPG
./JPG/IMG_0008.JPG
./JPG/IMG_0009.JPG

所以现在我要...

for f in ./JPG/* ; do touch ${f}.JPG ; done && ls ./JPG

IMG_0001.JPG      IMG_0003.JPG.JPG  IMG_0006.JPG      IMG_0008.JPG.JPG
IMG_0001.JPG.JPG  IMG_0004.JPG      IMG_0006.JPG.JPG  IMG_0009.JPG
IMG_0002.JPG      IMG_0004.JPG.JPG  IMG_0007.JPG      IMG_0009.JPG.JPG
IMG_0002.JPG.JPG  IMG_0005.JPG      IMG_0007.JPG.JPG
IMG_0003.JPG      IMG_0005.JPG.JPG  IMG_0008.JPG

让我们看看find现在向我们展示了什么:

find ./JPG -iname IMG_[0-9][0-9][0-9][0-9].JPG

###OUTPUT###

./JPG/IMG_0001.JPG
./JPG/IMG_0002.JPG
./JPG/IMG_0003.JPG
./JPG/IMG_0004.JPG
./JPG/IMG_0005.JPG
./JPG/IMG_0006.JPG
./JPG/IMG_0007.JPG
./JPG/IMG_0008.JPG
./JPG/IMG_0009.JPG

所以你看,因为我的.JPG.JPG文件名不以字符串结尾,所以[0-9]{4}.JPG find它们一开始就不会显示出来。\*在该搜索字符串的末尾添加 a-iname可能更适合您。

不过,正如另一个答案提到的,另一个问题是你的外壳球。例如:

sh -cx 'cd ./JPG ; find . -iname IMG_[0-9][0-9][0-9][0-9].JPG'                                                                      
+ cd ./JPG
+ find . -iname IMG_0001.JPG IMG_0002.JPG IMG_0003.JPG IMG_0004.JPG IMG_0005.JPG IMG_0006.JPG IMG_0007.JPG IMG_0008.JPG IMG_0009.JPG
find: paths must precede expression: IMG_0002.JPG
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

你看?如果 shell 可以,它会[glob]在您将命令字符串传递给 之前得到的那些不带引号的方括号中find。它可能看起来应该更像这样:

find "$1" -iname 'IMG_[0-9][0-9][0-9][0-9].JPG*'

关于最后一点,您可能不需要那么多递归循环。我认为 - 只要你只想删除旧的cp --suffix=.JPG -backups - 这可能可以作为所有内容的可行替代品shopt...

(   dir=$2
    set -- "${dir}"/*[0-9].???
    while [ -e "$1" ]
    do  cmp "$1" "${1}.JPG" &&
        rm -v "${1}.JPG" 2>&1
    shift ; done
) 2>/dev/null

不过,不可否认,这可以通过一个方法进行很大程度的优化有点递归循环如:

(   dir=$2
    set -- "${dir}"/*[0-9].???
    while [ -e "$1" ]
    do  until [ -e "${1}.JPG" ] 
        do shift || break; done
        cmp "$1" "${1}.JPG" &&
        rm -v "${1}.JPG" 2>&1
    ${1+shift} ; done
) 2>/dev/null 

我说有点因为whileuntil循环都在相同的参数集上运行,甚至从不测试同一个文件两次,所以它们并不完全一样递归即使它们是嵌套的。无论如何,优化在于不需要exec任何其他过程until,并且尽可能仅依赖 shell 内置函数。

答案2

for你提到的循环给我抛出了一个错误。但当我对方括号使用转义字符时,它工作得很好。所以我的 for 循环会是这样的:

find $1 -iname IMG_\\[0-9\\]\\[0-9\\]\\[0-9\\]\\[0-9\\].JPG -exec cp -b --suffix=.JPG  {} $2 \;

相关内容