ファイル名に基づいて画像をフィルタリングするのはなぜですか?

ファイル名に基づいて画像をフィルタリングするのはなぜですか?

以下のコードを使用して画像をフィルタリングするときは、ファイルもフィルタリングする必要があります。

例えば、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最初は表示されません。\*その検索文字列の末尾に を追加すると、うまく-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]

願いより?シェルが可能な場合は、[glob]コマンド文字列を渡す前に得られた引用符で囲まれていない角かっこ内にありますfind。おそらく次のようになります。

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

最後の点に関しては、おそらくそれほど多くの再帰ループは必要ありません。私の考えでは、古いバックアップのみを削除したい場合は、すべてをcp --suffix=.JPG -b置き換えるための実行可能な方法になる可能性があります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ループはすべて同じパラメータセットで実行され、同じファイルを2回テストしないため、まったく同じではありません。再帰入れ子になっていても同じです。とにかく最適化は、exec追加の手順を必要とせず、until可能な場合はいつでもシェル組み込みにのみ依存することで構成されます。

答え2

forあなたが言及したループで私にエラーが発生しました。しかし、角かっこにエスケープ文字を使用すると正常に動作します。したがって、私のforループは次のようになります。

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

関連情報