Bash-アーカイブ名からファイル名、不適切な一致(zip、cdg、mp3)
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ファイルの名前を付けてほしかったのですが、それが現在行われていることです。

私が行った変更...
pair_existsをクリーンアップしました
unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'
cdgとmp3_nameの抽出をクリーンアップし、awkを削除しました
cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$')
mp3_name=$(unzip -Z1 "$i" | grep -E -- '\.mp3$|\.MP3$')
新しいbase_nameの提案とエコーの削除が組み込まれました
base_name="${zip_name%.*}"
new_cdg_name="$base_name.cdg"
new_mp3_name="$base_name.mp3"
「printf」デバッグ行を追加しました(150k以上のファイルを実行するとコメントアウトされます)
printf 'cdg_name = [%s]\n' "$cdg_name"
printf 'mp3_name = [%s]\n' "$mp3_name"
ツールセットとの一貫性を保つために、解凍ツールを解凍に変更します
unzip -qq "$i"
修正がどこで行われたかはわかりませんが、@ G-Manが「ReinstateMonica」と言ってくれて、これを手伝ってくれて、非常にしっかりしたアドバイスをしてくれて本当に感謝しています。
ありがとうございました!
回答
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 …
.cdg
cdg_name
mv
単純化するために、変更することができます
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
)を。言う理由はほとんどありません。実際、そうする理由は決してないと言いたくなりますが、誰かがおそらくそれが有益である奇妙なコーナーケースを特定するでしょう。具体的には、
$(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 - I
Plan - I
政治的に正しくないというリスクを冒して、あなたが犯罪を解決しようとしている警察であり、あなたができることは双眼鏡で犯罪者の本部の外に座ることだけだと想像してください。盗聴や情報提供者を雇って、建物の中で何が起こっているのかを知ることができれば、もっといいのではないでしょうか。デバッグが犯罪を解決しようとしているようなものです-外部の情報(すなわち、の出力ながら
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
。厳密に言えば、これは限り私がここにいると、コメントすることが、必要があります:どこ内のメンバーファイルの名前はという考えもらったの
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
上で述べたように、これ
I\'d Do Anything
はパズルです。しかし、実際には、コンマ、バッククォート、または非ASCII文字(「é」、「Φ」、「Ø」、「θ」、「½」、「∞」など)に関連する問題の例はありますか?