Bash-아카이브 이름을 파일 이름으로, 부적절한 일치 (zip, cdg, mp3)

Dec 07 2020

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 파일의 이름을 취하기를 원했고 그것이 지금하고있는 일입니다.

내가 변경 한 사항은 ...

  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이 '모니카 복원'을 말하고이를 통해 저를 돕고 매우 확실한 조언을 해주셔서 정말 감사합니다.

감사합니다!


답변

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"
    

    추신 : 엄밀히 말하면 위의 인용문은 필요하지 않지만, 좋은 이유가없는 한 항상 사용하는 것이 좋습니다.
    잘못된 맥락에서 PPS는, 변경 등의 작업을 수행 할 수 로 (하나로 즉, 압축 여러 공간).$(echo "something")Plan  - IPlan - I

  4. 정치적으로 부정확 할 수있는 위험에 처해있는 당신이 범죄를 해결하려는 경찰이고, 당신이 할 수있는 일은 쌍안경을 들고 범죄자 본부 밖에 앉아있는 것 뿐이라고 상상해보십시오. 도청이나 정보원을 구해 건물 내부에서 무슨 일이 벌어지고 있는지 알 수 있다면 훨씬 나아지지 않을까요? 디버깅은 범죄를 해결하려는 것과 같습니다. 외부 정보 (즉, 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.

  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가 아닌 문자 (예 : 'é', 'Φ', 'Ø', 'θ', '½'또는 '∞')와 관련된 문제의 예가 있습니까?