Bash-アーカイブ名からファイル名、不適切な一致(zip、cdg、mp3)

Dec 07 2020

zipアーカイブ内の2つの特定の拡張機能をチェックするスクリプトを作成しました。アーカイブにファイルが2つしかないかどうかを判断するために、いくつかのチェックが行われ、それらが処理されます。アーカイブの数が2未満の場合、アーカイブは「BAD」フォルダーに移動します。アーカイブに3つ以上ある場合は、アーカイブを「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 -----

ZIPファイル名: 

     CB30035-05-シンプルプラン-私は何でもします.zip

ZIP内のファイル:

     CB30035-05-シンプルプラン-I'dDo Anything.cdg
     CB30035-05-シンプルプラン-私は何でもします.mp3

エラー:

     mv:統計できません './CB30035-05-Simple PlanI \' d Do Anything.cdg ':そのようなファイルまたはディレクトリはありません
     mv:統計できません './CB30035-05-Simple PlanI \' d Do Anything.mp3 ':そのようなファイルまたはディレクトリはありません

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

ZIPファイル名:

     CBSE5-0068-カーペンターズ、-私たちが知っているすべての人のために.zip

ZIP内のファイル:

     cbscdge450-5-0068-カーペンターズ-ふたりの誓い.cdg
     cbscdge450-5-0068-カーペンターズ-ふたりの誓い.mp3

エラー:
mv:統計できません './cbscdge450-5-0068-カーペンターズ-ふたりの誓い.cdg \ ncbscdge450-5-0068-カーペンターズ-ふたりの誓い.mp3':そのようなファイルやディレクトリはありません

私は同様の問題を探し回っていましたが、見つけたトピックが私の問題に実際に適合しなかったか、コードの一部がスクリプトに組み込む方法を理解するために少し頭を悩ませていました。

助けていただければ幸いです。ありがとうございました!

(注:上記のスクリプトの「awk」が何も実行していないことを認識しています。「unzip-Z1」に移動しました。これにより、zipファイルからファイル名を取得するという以前の取り組みが解決されたようです。必要になった場合に備えて、そのままにしておくために調整しました。)



EDIT 2020120601:


@Wielandに応えて、zipファイル名からダブルスペースを削除しました。しかし、内部のファイルにダブルスペースを残しました。多くのファイルがあるので、すべてのファイルの内部を修正することはできないので、それらをそのまま修正する方法を理解する必要があります。zipファイルの二重スペースを削除しても結果は変わりませんでした。

@steeldriverに応えて、ここにもう少し情報があります。以下は、私が使用しようとした各コマンドの戻り値です(7zaに注意してください...ファイル名を生成する方法がないため、以前はawkを使用していました)。

また、コードを読み取るように変更しましたが、結果は変わりませんでしたが、そのベースをカバーすることに同意します。\.cdg$|\.CDG$|\.mp3$|\.MP3$

zipinfo -1 "CB30035-05 --SIMPLE PLAN-I'D DO ANYTHING.zip" 

  CB30035-05-シンプルなPlanI'dDo Anything.cdg
  CB30035-05-シンプルなPlanI'dDo Anything.mp3

unzip -Z1 "CB30035-05 --SIMPLE PLAN-I'D DO ANYTHING.zip" 

  CB30035-05-シンプルなPlanI'dDo Anything.cdg
  CB30035-05-シンプルなPlanI'dDo Anything.mp3

7za -ba l "CB30035-05 --SIMPLE PLAN-I'D DO ANYTHING.zip"           

   2003-06-27 14:41:56 .... A 1516512 379652CB30035-05-単純なPlanI'dDo Anything.cdg
   2003-06-27 14:42:22 .... A 3369876 3112004CB30035-05-シンプルなPlanI'dDo Anything.mp3



編集2020100701:


@ G-Manは「モニカを復活させる」と言います

あなたの説明の周りにたくさんの詳細を包んでくれてありがとう。感謝します。提案されたmodをスクリプトに組み込みます。に関してで

「.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   $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

Linux

なぜそれが起こっているのか私には分かりません。それをしばらく見た後、私の一部はたぶん多分と思います...私はどういうわけか私の環境を台無しにしました。私はこれまでこのようなクロス問題を実行したことがなく、髪を抜いてしまいます!

今!あなたにこのすべての情報を与えました、そして多分私はあなたに十分に与えていません。しかし、私はあなたに言う必要があります。コードに変更を加えた後、それは正しい結果を生み出しています!私のシステムはまだファイル名から「-」を取り除いていますが、それは望ましい最終結果を生み出しています。私はファイルに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」デバッグ行を追加しました(150k以上のファイルを実行するとコメントアウトされます)
    printf 'cdg_name = [%s]\n' "$cdg_name"
    printf 'mp3_name = [%s]\n' "$mp3_name"

  5. ツールセットとの一貫性を保つために、解凍ツールを解凍に変更します
    unzip -qq "$i"

修正がどこで行われたかはわかりませんが、@ G-Manが「ReinstateMonica」と言ってくれて、これを手伝ってくれて、非常にしっかりしたアドバイスをしてくれて本当に感謝しています。

ありがとうございました!


回答

1 G-ManSays'ReinstateMonica' Dec 07 2020 at 21:17
  1. Steeldriverのコメントは、ほぼ確実に問題の一部を特定しています。「コードを読み取りに変更しても、結果が変わらなかった」場合は、間違って実行しました。具体的には、不完全に実行しました。問題の一部はコマンドにあります\.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_namemv

  2. 単純化するために、変更することができます

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

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

    (のc ountオプションを使用grep)または

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

    (使用してのgnoreケースオプション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_nameにより、2つの名前の連結に設定されていることが明らかになり、に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

    と ?の間の 何かを表示するコマンドを表示していない場合PlanI

  6. 上で述べたように、これI\'d Do Anythingはパズルです。しかし、実際には、コンマ、バッククォート、または非ASCII文字(「é」、「Φ」、「Ø」、「θ」、「½」、「∞」など)に関連する問題の例はありますか?