.png)
두 가지 특정 확장에 대한 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 ....A 3369876 3112004 CB30035-05 - Simple Plan 뭐든지 할게.mp3
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 컴퓨터에서 생성되는 내용을 다시 게시하겠습니다.
윈도우:
운영 체제:
왜 이런 일이 발생하는지 모르겠습니다. 잠시 동안 그것을 살펴본 후 내 일부는 어쩌면... 내가 내 환경을 어지럽혔는지 생각했습니다. 이전에 이런 문제를 겪어본 적이 없어서 미칠 지경입니다!
지금! 이 모든 정보를 제공한 후에도 충분히 제공하지 않았을 수도 있습니다. 하지만 말해야 해요. 코드를 변경하면 올바른 결과가 생성됩니다! 내 시스템은 여전히 파일 이름에서 "-"를 제거하고 있지만 원하는 최종 결과를 생성하고 있습니다. 나는 파일이 지금 하고 있는 일인 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" 디버그 라인 추가(150,000개 이상의 파일을 실행할 때 주석 처리됨)
printf 'cdg_name = [%s]\n' "$cdg_name"
printf 'mp3_name = [%s]\n' "$mp3_name"
도구 세트와 일관성을 유지하기 위해 압축 해제기를 압축 해제로 변경했습니다.
unzip -qq "$i"
어디서 문제가 해결되었는지는 모르겠지만 @G-Man이 "모니카 복원"이라고 말하면서 이 문제를 해결하는 데 도움을 주고 정말 확실한 조언을 해주셔서 정말 감사합니다.
감사합니다!
답변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 …
.cdg
cdg_name
일련의이름이 두 개, 줄 바꿈으로 구분됩니다. 이는 오류 메시지를 보면 분명합니다mv
.단순화 목적으로 변경할 수 있습니다.
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
.말할 이유가 거의 없습니다. 사실, 나는 이것을 할 이유가 전혀 없다고 말하고 싶지만, 누군가는 그렇게 하는 것이 유익할 이상한 극단적인 경우를 발견할 수도 있습니다. 구체적으로,
$(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는 잘못된 컨텍스트에서 변경(즉, 여러 공백을 하나로 압축)과 같은 작업을 수행할 수 있습니다.$(echo "something")
Plan - I
Plan - I
정치적으로 올바르지 않을 수도 있지만, 당신이 범죄를 해결하려는 경찰관이고 당신이 할 수 있는 일은 쌍안경을 들고 범죄자 본부 밖에 앉아 있는 것뿐이라고 상상해 보십시오. 건물에서 무슨 일이 일어나고 있는지 알 수 있도록 버그나 정보 제공자를 얻을 수 있다면 더 좋지 않을까요? 디버깅은 범죄를 해결하려는 것과 같습니다. 외부 정보(즉,
zipinfo
및 의 출력7za
, 별도로 실행)는 문제를 이해하는 데 중요하지만 내부 정보를 얻는 데는 정말 도움이 됩니다. 따라서 일상적인 디버깅 단계로 다음과 같은 문을 추가하는 것이 좋습니다.printf 'cdg_name = [%s]\n' "$cdg_name" printf 'mp3_name = [%s]\n' "$mp3_name"
스크립트에. 이는 분명히
cdg_name
두 이름을 연결하여 설정 되므로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 문자와 관련된 문제의 예가 있습니까?