Bash - アーカイブ名をファイル名に、間違った一致(zip、cdg、mp3)

Bash - アーカイブ名をファイル名に、間違った一致(zip、cdg、mp3)

2つの特定の拡張子のzipアーカイブを確認するスクリプトを書いています。アーカイブにファイルが2つしかないことを確認してから処理します。アーカイブが2つ未満の場合、そのアーカイブは「BAD」フォルダに移動さ​​れます。アーカイブが2つ以上の場合は、そのアーカイブを「FIX」ディレクトリに移動します。

プロセスのステップは、ファイルを抽出し、zipアーカイブと同じ名前に名前を変更することです。

条件が完璧であれば、すべてが順調に進みます。しかし、条件が完璧ではない場合、状況は悪くなります。

私が経験している問題は、ファイルに正しい2つのファイル名と拡張子がある場合でも、ファイルに特殊文字(Ø、バックティック、カンマ、アポストロフィなど)が含まれている場合に処理されることです。 )正規表現の構文や式と同じです。

コードは次のとおりです。

#! /bin/bash

prefix="0000_"

mkdir -p ${prefix}{DONE,FIX,BAD}

shopt -s nocaseglob
for i in *.ZIP;
    do
        zip_name="$i"
        pair_exists=$(unzip -Z1 "$i" | grep -E -- '.cdg|.CDG|.mp3|.MP3' | wc -l)
        log="${prefix}LOG.txt"

        if [ $pair_exists -eq 2 ]
            then
                cdg_name=$(unzip -Z1 "$i" | grep -E -- '.cdg|.CDG' | awk '{print substr($0,index($0,$1))}')
                mp3_name=$(unzip -Z1 "$i" | grep -E -- '.mp3|.MP3' | awk '{print substr($0,index($0,$1))}')
                new_cdg_name="$(echo "${zip_name%.*}.cdg")"
                new_mp3_name="$(echo "${zip_name%.*}.mp3")"
                7za x "$i" -aoa -y -ba >> ./$log
                mv ./"$cdg_name" ./"$new_cdg_name"
                mv ./"$mp3_name" ./"$new_mp3_name"
                mv ./"$zip_name" ./${prefix}DONE/

        elif [ $pair_exists -gt 2 ]
            then
                echo ""
                echo "NEEDS FIXED: $zip_name"
                mv ./"$zip_name" ./${prefix}FIX/

        elif [ $pair_exists -lt 2 ]
            then
                echo ""
                echo "ARCHIVE IS BAD: $zip_name"
                mv ./"$zip_name" ./${prefix}BAD/

        else
                echo ""
                echo "MUST BE BROKE!"
                echo ""
        fi
    done
exit

MV声明を見るまではすべてが素晴らしかった。

                mv ./"$cdg_name" ./"$new_cdg_name"
                mv ./"$mp3_name" ./"$new_mp3_name"

おそらくmvがここで使用するのに適した方法ではないかもしれませんが、名前を変更するのに深刻な問題があるかもしれません。変数の文字を実行する操作と見なさないように、コマンドに指示するコードがさらに必要だと思います。

私が見た現象は次のとおりです...

----- 例 1 -----

圧縮ファイル名:

     CB30035-05 - Simple Plan - 何でもします.zip

Zip内のファイル:

     CB30035-05 - Simple Plan - 何でもします。cdg
     CB30035-05 - Simple Plan - なんでもやろうと思っています。mp3

間違い:

     mv: './CB30035-05 - Simple PlanI\'d Do Anything.cdg' を stat できません。そのファイルやディレクトリはありません。
     mv: './CB30035-05 - Simple PlanI\'d Do Anything.mp3'をstatできません。そのファイルやディレクトリはありません。

----- 例 2 -----

圧縮ファイル名:

     CBSE5-0068 - 大工、私たちが知っているもの.zip

Zip内のファイル:

     cbscdge450-5-0068 - 大工 - 私たちが知っているもの.cdg
     cbscdge450-5-0068 - 大工 - 私たちが知っていること.mp3

間違い:
mv: stat './cbscdge450-5-0068 - Carpenters - For All We Know.cdg\ncbscdge450-5-0068 - Carpenters - For All We Know.mp3': 該当するファイルまたはディレクトリはありません。

私は似たような質問を見つけましたが、私が見つけたトピックが私の問題に実際に合っていないか、いくつかのコードが私のスクリプトにどのように統合されるかを理解しようとして頭の上に少し外れました。

助けてくれてありがとう。ありがとうございます!

(注:上記のスクリプトの「awk」は何もしないことを知っています。「unzip -Z1」に移動しましたが、zipファイルからファイル名を取得しようとする以前の作業は解決されたようです。必要な場合に備えてアーカイブするように調整してください。)



2020120601 編集:


@Wielandに応答してzipファイル名から二重スペースを削除しました。ただし、内部ファイルに二重スペースが残ります。ファイルが多すぎて各ファイルの内部を修正することができないので、そのまま修正できる方法を工夫しなければなりません。 zipファイルから二重スペースを削除しても結果は変わりませんでした。

@steeldriverに応答して、詳細は次のとおりです。これは私が使用しようとした各コマンドの戻り結果です(注7za ...ファイル名だけを生成する方法がないので、以前はawkを使用しました)。

また、コードを read に変更しましたが、\.cdg$|\.CDG$|\.mp3$|\.MP3$結果は変更されませんでしたが、基本事項が扱われることに同意します。

zipinfo -1 "CB30035-05 - 簡単な計画 - 何でもします。zip"

  CB30035-05 - 簡単な計画私は何でもします。cdg
  CB30035-05 - 簡単な計画で何でもやる。mp3

unzip -Z1 "CB30035-05 - 簡単な計画 - 何でもします。zip"

  CB30035-05 - 簡単な計画私は何でもします。cdg
  CB30035-05 - 簡単な計画で何でもやる。mp3

7za -ba l "CB30035-05 - 簡単な計画 - 何でもします。zip"           

   2003-06-27 14:41:56 ....A 1516512 379652 CB30035-05 - シンプルプラン何でもします。cdg
   2003-06-27 14:42:22 ...



2020120701 編集:


@G-Manは「モニカ復元」と言います。

説明にあまりにも詳細を含めていただきありがとうございます。ありがとうございます。提案したモードをスクリプトに統合します。 ~について

".cdg$|.CDG$|.mp3$|.MP3$を読み取るようにコードを変更したが、結果が変わらなかったら"間違っているのです...

私はあなたの例に正確に従ったと確信しています。私はこれをしたとコメントしましたが、私のコメントからバックスラッシュが削除されました。 grep "c"も実装しました。しかし、「i」オプションは明らかに非常に欠けています。これで確実に解決されます。

今のコードはこんな感じです...

#! /bin/bash

prefix="00001_"

mkdir -p ${prefix}{DONE,FIX,BAD}

shopt -s nocaseglob
for i in *.ZIP;
    do
        zip_name="$i"
        pair_exists=$(unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$')

        if [ $pair_exists -eq 2 ]
            then
                cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$')
                mp3_name=$(unzip -Z1 "$i" | grep -E -- '\.mp3$|\.MP3$')

                base_name="${zip_name%.*}"
                new_cdg_name="$base_name.cdg"
                new_mp3_name="$base_name.mp3"

                        printf 'cdg_name = [%s]\n' "$cdg_name"
                        printf 'mp3_name = [%s]\n' "$mp3_name"

                unzip -qq "$i"
                mv -- "${cdg_name}" "${new_cdg_name}"
                mv -- "${mp3_name}" "${new_mp3_name}"
                mv ./"$zip_name" ./${prefix}DONE/

        elif [ $pair_exists -gt 2 ]
            then
                echo ""
                echo "NEEDS FIXED: $zip_name"
                mv ./"$zip_name" ./${prefix}FIX/

        elif [ $pair_exists -lt 2 ]
            then
                echo ""
                echo "ARCHIVE IS BAD: $zip_name"
                mv ./"$zip_name" ./${prefix}BAD/

        else
                echo ""
                echo "HMM"
                echo ""
        fi
    done
exit

変更もマージしました。

デバッグに関しては「echo」を再利用しました。これが私のテストスクリプトの内容です...

echo ""
echo "-----"
echo   $pair_exists
echo   $zip_name
echo   $cdg_name
echo   $mp3_name
echo   $new_cdg_name
echo   $new_mp3_name
echo   $prefix
echo   $log
echo "-----"
echo ""

「printf」と同じ結果を生成します。しかし、私はあなたの奇抜なスタイルが好きで、あなたのスタイルを採用します。 :)

回答ポイント5. 7z.exeを使用してこのアイデアを得ました。実際にはGUIを通して見ることができます。それでは、私のWindowsコンピュータで見たスクリーンショットを公開し、Linuxコンピュータで作成された内容を再公開します。

Windows:

ここに画像の説明を入力してください。

オペレーティングシステム:

ここに画像の説明を入力してください。

なぜこれが起こるのかわかりません。しばらくそれを見た後、私の一部はたぶん...私が私の環境を乱したかどうかを考えました。以前はこのような問題を経験したことがないので狂​​った地境です!

今! これらすべての情報を提供した後も十分に提供していない可能性があります。しかし、言わなければなりません。コードを変更すると、正しい結果が生成されます!私のシステムはまだファイル名から「-」を削除していますが、目的の最終結果を生成しています。私は今ファイルしているzipファイルの名前を使用したいと思います。

ここに画像の説明を入力してください。

私が作った変更は...

  1. pair_exists クリーンアップ
    unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'

  2. cdg と mp3_name 抽出をクリーンアップし、awk を削除します。
    cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$')
    mp3_name=$(unzip -Z1 "$i" | grep -E -- '\.mp3$|\.MP3$')

  3. 新しいbase_name提案をマージし、エコーを削除しました。
    base_name="${zip_name%.*}"
    new_cdg_name="$base_name.cdg"
    new_mp3_name="$base_name.mp3"

  4. 「printf」デバッグ行を追加する(150,000を超えるファイルを実行するときにコメントアウトされます)
    printf 'cdg_name = [%s]\n' "$cdg_name"
    printf 'mp3_name = [%s]\n' "$mp3_name"

  5. ツールセットとの整合性を維持するために、圧縮解除器を圧縮解除に変更しました。
    unzip -qq "$i"

どこで問題が解決したのかはわかりませんが、@G-Manが「モニカの復元」と言って、この問題を解決するのに役立ち、本当に確実なアドバイスをいただきありがとうございます。

ありがとうございます!


ベストアンサー1

  1. スチールドライバーレビュー問題の一部はほぼ確実に識別されます。 「読んだコードを変更しましたが\.cdg$|\.CDG$|\.mp3$|\.MP3$ 結果は変更されませんでした」と間違っているのです。特に不完全に行っているのです。問題の一部はコマンドです

    cdg_name=$(unzip -Z1 "$i" | grep -E -- '.cdg|.CDG' | awk '{print substr($0,index($0,$1))}')
    

    に変更する必要があります。

    cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$' | awk '{print substr($0,index($0,$1))}')
    

    一致するため、次のように設定されます。cbscdge450-5-0068 - Carpenters ….cdgcdg_name一連の名前が2つ、改行で区切られます。  これはエラーメッセージを見ると明らかですmv

  2. 簡素化の目的で変更できます。

    unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$|\.mp3$|\.MP3$' | wc -l
    

    到着

    unzip -Z1 "$i" | grep -Ec -- '\.cdg$|\.CDG$|\.mp3$|\.MP3$'
    

    (使用計算オプションgrep)または

    unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'
    

    (使用)の大文字と小文字のオプションを無視しますgrep

  3. 言う理由はほとんどありません。実際、私はこれを行う理由がまったくないと言いたいのですが、誰かがそうすることが有益である奇妙な極端なケースを見つけるかもしれません。具体的には、$(echo "something")

    new_cdg_name="$(echo "${zip_name%.*}.cdg")"
    new_mp3_name="$(echo "${zip_name%.*}.mp3")"
    

    に変更されることがあります

    new_cdg_name="${zip_name%.*}.cdg"
    new_mp3_name="${zip_name%.*}.mp3"
    

    私はそれらを次のように変更することもできます。

    base_name="${zip_name%.*}"
    new_cdg_name="$base_name.cdg"
    new_mp3_name="$base_name.mp3"
    

    PS厳密に言えば、上記の引用は必須ではありませんが、そうしない妥当な理由がない限り、常に引用を使用するのが最善です。
    PPSは、間違ったコンテキストで変更(つまり、複数のスペースを1つに圧縮)などの操作を実行する可能性があります。$(echo "something")Plan  - IPlan - I

  4. 政治的には正しくないかもしれませんが、あなたが犯罪を解決しようとする警察官であり、あなたができることは双眼鏡を持って犯罪者本部の外に座っているだけだと想像してください。建物で何が起こっているのかを知るためにバグや情報提供者を手に入れることができれば、それは良いことではありませんか?デバッグは犯罪を解決したいのと同じです。外部情報(つまり、zipinfoおよび出力7za、別々に実行)は問題を理解するために重要ですが、内部情報を取得するのには本当に役立ちます。したがって、日常的なデバッグ手順として、次の文を追加することをお勧めします。

    printf 'cdg_name = [%s]\n' "$cdg_name"
    printf 'mp3_name = [%s]\n' "$mp3_name"
    

    スクリプトに。これは明らかにcdg_name2つの名前を連結して設定されるため、I'd Do Anything追跡に役立ちますI\'d Do Anything

  5. 厳密に言えば、これはコメントでなければなりませんが、私がここにいる限り:そこにあるメンバーファイルの名前がどこにあるという考えをどこで得ましたかCB30035-05 - SIMPLE PLAN - I'D DO ANYTHING.zip

    • CB30035-05 - Simple Plan - I'd Do Anything.cdgそして
    • CB30035-05 - Simple Plan - I'd Do Anything.mp3

    明示的なコマンドを表示しない場合何もない そして  Plan間  I

  6. 上記のように、これはI\'d Do Anythingパズルです。しかし、実際には、コンマ、逆引用符、または「é」、「Φ」、「Ø」、「θ」、「½」、または「無限大」などの非ASCII文字に関連する問題の例はありますか?

おすすめ記事