Bash-아카이브 이름을 파일 이름으로, 부적절한 일치 (zip, cdg, mp3)
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 ----- ZIP 파일 이름 : CB30035-05-간단한 계획-I 'D DO ANYTHING.zip ZIP 내 파일 : CB30035-05-Simple Plan-I 'd Do Anything.cdg CB30035-05-Simple Plan-I 'd Do Anything.mp3 오류: mv : not stat './CB30035-05-Simple PlanI \'d Do Anything.cdg ': No such file or directory mv : cannot stat './CB30035-05-Simple PlanI \'d Do Anything.mp3 ': No such file or directory ----- 예 2 ----- ZIP 파일 이름 : CBSE5-0068-목수, THE-FOR ALL WE KNOW.zip ZIP 내 파일 : cbscdge450-5-0068-Carpenters-For All We Know.cdg cbscdge450-5-0068-Carpenters-For All We Know.mp3 오류: mv : cannot 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를 사용했습니다).
또한 읽을 코드를 변경했지만 결과가 변경되지는 않았지만 해당 기반을 다룰 것에 동의합니다.\.cdg$|\.CDG$|\.mp3$|\.MP3$
zipinfo -1 "CB30035-05-SIMPLE PLAN-I 'D DO ANYTHING.zip" CB30035-05-Simple PlanI'd Do Anything.cdg CB30035-05-그대 .mp3 unzip -Z1 "CB30035-05-간단한 계획-I 'D DO ANYTHING.zip" CB30035-05-Simple PlanI'd Do Anything.cdg CB30035-05-그대 .mp3 7za -ba l "CB30035-05-SIMPLE PLAN-I 'D DO ANYTHING.zip" 2003-06-27 14:41:56 .... A 1516512 379652 CB30035-05-Simple PlanI'd Do Anything.cdg 2003-06-27 14:42:22 .... A 3369876 3112004 CB30035-05-Simple Plan I 'd Do Anything.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 상자에서 생성하는 내용을 다시 게시 할 것입니다.
WINDOWS :

리눅스 :

왜 그런 일이 일어나는지 전혀 모르겠습니다. 그것을 잠시 보니, 제 일부는 아마도 ... 어떻게 든 환경을 망쳤습니다. 나는 전에 이와 같은 문제를 겪어 본 적이 없으며 머리카락을 뽑아 버립니다!
지금! 이 모든 정보를 제공했지만 충분히 제공하지 않았을 수 있습니다. 하지만 말씀 드릴 필요가 있습니다. 코드를 변경하면 올바른 결과가 생성됩니다! 내 시스템이 여전히 파일 이름에서 "-"를 제거하더라도 원하는 최종 결과를 생성합니다. 나는 파일이 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이 '모니카 복원'을 말하고이를 통해 저를 돕고 매우 확실한 조언을 해주셔서 정말 감사합니다.
감사합니다!
답변
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"
추신 : 엄밀히 말하면 위의 인용문은 필요하지 않지만, 좋은 이유가없는 한 항상 사용하는 것이 좋습니다.
잘못된 맥락에서 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가 아닌 문자 (예 : 'é', 'Φ', 'Ø', 'θ', '½'또는 '∞')와 관련된 문제의 예가 있습니까?