Bash - Nome do arquivo para nome do arquivo, correspondência imprópria (zip, cdg, mp3)

Dec 07 2020

Eu escrevi um script que verifica a existência de duas extensões específicas em um arquivo zip. Algumas verificações são feitas para determinar se o arquivo tem apenas 2 arquivos e depois processá-los. Se o arquivo tiver menos de 2, ele moverá o arquivo para uma pasta "RUIM". Se o arquivo tiver mais de 2, ele moverá o arquivo para um diretório "FIX".

A etapa do processo é extrair os arquivos e renomeá-los com o mesmo nome do arquivo zip.

Tudo isso funciona bem, quando as condições são perfeitas. Mas quando eles não são perfeitos ... fica feio.

Estou enfrentando um caso em que, embora os arquivos possam ter os 2 arquivos e a extensão corretos, se os arquivos tiverem caracteres especiais (como Ø, crases, vírgula, apóstrofo, etc.) ... eles são processados ​​(presumo) como sintaxe regex ou expressões.

Aqui está o código:

#! /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

Tudo está bem, até eu chegar às minhas declarações.

                mv ./"$cdg_name" ./"$new_cdg_name"
                mv ./"$mp3_name" ./"$new_mp3_name"

Sinto que talvez o mv não seja o método correto a ser usado aqui, mas também estava tendo sérios problemas com a renomeação. Acho mais que preciso de algum código que diga aos comandos para não tratar quaisquer caracteres dentro das variáveis ​​como ações a serem executadas.

Aqui está o que vejo acontecendo ...

----- EXEMPLO 1 -----

NOME DO ARQUIVO ZIP: 

     CB30035-05 - PLANO SIMPLES - EU FARIA QUALQUER COISA.zip

ARQUIVOS DENTRO DO ZIP:

     CB30035-05 - Simple Plan - Eu faria qualquer coisa.cdg
     CB30035-05 - Simple Plan - Eu Faria Qualquer Coisa.mp3

ERRO:

     mv: não é possível stat './CB30035-05 - Simple PlanI \' d Do Anything.cdg ': Não existe tal arquivo ou diretório
     mv: não é possível stat './CB30035-05 - Simple PlanI \' d Do Anything.mp3 ': Não existe tal arquivo ou diretório

----- EXEMPLO 2 -----

NOME DO ARQUIVO ZIP:

     CBSE5-0068 - CARPINTEIROS, O - PARA TODOS NÓS SABEMOS.zip

ARQUIVOS DENTRO DO ZIP:

     cbscdge450-5-0068 - Carpinteiros - For All We Know.cdg
     cbscdge450-5-0068 - Carpinteiros - Para tudo que sabemos.mp3

ERRO:
mv: não é possível stat './cbscdge450-5-0068 - Carpenters - For All We Know.cdg \ ncbscdge450-5-0068 - Carpenters - For All We Know.mp3': Não existe esse arquivo ou diretório

Procurei por um problema semelhante, mas os tópicos que encontrei não se encaixam realmente no meu problema ou algum código estava um pouco além da minha cabeça para tentar descobrir como incorporar ao meu script.

Eu apreciaria qualquer ajuda. Obrigado!

(NOTA: Estou ciente de que meu "awk" no script acima não está fazendo nada. Mudei para "unzip -Z1" e isso parece ter resolvido meus esforços anteriores para apenas retirar o nome do arquivo dos arquivos zip. Eu saí e ajustou-o apenas para mantê-lo por perto, caso eu precisasse.)



EDIT 2020120601:


Em resposta a @Wieland, removi o espaço duplo do nome do arquivo zip. Mas deixou o espaço duplo nos arquivos dentro. Não poderei consertar o interior de cada arquivo, pois há muitos, então preciso descobrir como consertá-los da forma como estão. A remoção do espaço duplo no arquivo zip não alterou meus resultados.

Em resposta a @steeldriver, aqui estão mais algumas informações. Abaixo está o retorno de cada um dos comandos que tentei usar (observe o 7za ... ele não tem uma maneira de apenas produzir nomes de arquivo, então eu estava usando o awk anteriormente).

Eu também alterei o código para leitura e isso não alterou meus resultados, mas concordo que cobriria essa base.\.cdg$|\.CDG$|\.mp3$|\.MP3$

zipinfo -1 "CB30035-05 - PLANO SIMPLES - FARIA QUALQUER COISA.zip" 

  CB30035-05 - Simple PlanI'd Do Anything.cdg
  CB30035-05 - Simple PlanI'd Do Anything.mp3

descompacte -Z1 "CB30035-05 - PLANO SIMPLES - EU FARIA QUALQUER COISA.zip" 

  CB30035-05 - Simple PlanI'd Do Anything.cdg
  CB30035-05 - Simple PlanI'd Do Anything.mp3

7za -ba l "CB30035-05 - PLANO SIMPLES - FARIA QUALQUER COISA.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 PlanI'd Do Anything.mp3



EDIT 2020120701:


@G-Man diz 'Reintegrar Monica'

Obrigado por envolver tantos detalhes em suas explicações. Obrigado. Estarei incorporando seus mods sugeridos ao script. Em relação a

Se você “mudou o código para ler .cdg$|.CDG$| .mp3$|.MP3$ e isso não mudou meus resultados ”, então errou ...

Tenho certeza de que segui seu exemplo de perto. Eu tinha comentado em dizer que tinha feito isso, mas a barra invertida foi removida de meu comentário. Eu também já havia implementado o grep "c". Mas, aparentemente, falhou seriamente a opção "i". Isso definitivamente limparia tudo.

Aqui está o código como está agora ...

#! /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

Eu também incorporei suas mudanças.

Em relação a um debug, usei mais uma vez "echo". Isso é o que está no meu script de teste ...

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 ""

Estava produzindo a mesma coisa que seu "printf". No entanto, gosto muito dos seus modos extravagantes e adotarei o seu estilo. :)

Para responder ao ponto 5. Tive essa ideia ao usar o 7z.exe. Na verdade, olhando para ele por meio de uma GUI. Agora vou postar uma captura de tela do que minha caixa do Windows vê e novamente postarei o que minha caixa do Linux produz.

WINDOWS :

LINUX :

Não tenho ideia do por que isso está acontecendo. Depois de olhar para isso por um tempo, uma parte de mim pensa que talvez ... eu baguncei meu ambiente de alguma forma. Eu não cruzei um problema como este antes, e isso me deixa puxando meu cabelo para fora!

AGORA! Tendo dado a você todas essas informações, e talvez eu não tenha dado a você o suficiente. Mas eu preciso te contar. Depois de fazer suas alterações no código, ele está produzindo o resultado correto! Embora meu sistema ainda retire o "-" dos nomes de arquivo, ele está produzindo o resultado final desejado. Eu queria que os arquivos tivessem o nome do arquivo zip e é isso que ele está fazendo agora.

As mudanças que fiz ...

  1. limpou o pair_exists com
    unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'

  2. limpar a extração cdg e mp3_name e remover o awk
    cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$')
    mp3_name=$(unzip -Z1 "$i" | grep -E -- '\.mp3$|\.MP3$')

  3. incorporou a nova sugestão de base_name e remoção de echo
    base_name="${zip_name%.*}"
    new_cdg_name="$base_name.cdg"
    new_mp3_name="$base_name.mp3"

  4. adicionado as linhas de depuração "printf" (irá comentá-las ao fazer 150k + arquivo)
    printf 'cdg_name = [%s]\n' "$cdg_name"
    printf 'mp3_name = [%s]\n' "$mp3_name"

  5. Eu mudo o descompressor para descompactar para ficar consistente com o conjunto de ferramentas
    unzip -qq "$i"

Eu não sei onde a correção aconteceu, mas eu realmente agradeço a sua ajuda @ G-Man Says 'Reinstate Monica' e me ajudando com isso e dando alguns conselhos muito sólidos.

Obrigado!


Respostas

1 G-ManSays'ReinstateMonica' Dec 07 2020 at 21:17
  1. O comentário do steeldriver quase certamente identifica parte do problema. Se você “alterou o código para leitura e isso não mudou meus resultados”, então você fez isso errado - especificamente, você fez isso de forma incompleta. Parte do problema está no comando\.cdg$|\.CDG$|\.mp3$|\.MP3$

    cdg_name=$(unzip -Z1 "$i" | grep -E -- '.cdg|.CDG' | awk '{print substr($0,index($0,$1))}')
    

    que deve ser alterado para

    cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$' | awk '{print substr($0,index($0,$1))}')
    

    porque corresponde e, portanto, está sendo definido para a concatenação de ambos os nomes , separados por uma nova linha.   Isso fica bem claro na mensagem de erro.cbscdge450-5-0068 - Carpenters ….cdgcdg_namemv

  2. Apenas para fins de simplificação, você pode alterar

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

    para

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

    (utilizando o c opção de ount grep) ou mesmo

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

    (usando a opção de caso i gnore de grep).

  3. Quase nunca há razão para dizer . Na verdade, estou inclinado a dizer que nunca há uma razão para fazer isso, mas alguém provavelmente identificará um caso estranho em que seja benéfico. Especificamente,$(echo "something")

    new_cdg_name="$(echo "${zip_name%.*}.cdg")"
    new_mp3_name="$(echo "${zip_name%.*}.mp3")"
    

    pode ser alterado para

    new_cdg_name="${zip_name%.*}.cdg" new_mp3_name="${zip_name%.*}.mp3"
    

    Eu posso até ir mais longe a ponto de mudá-los para

    base_name="${zip_name%.*}" new_cdg_name="$base_name.cdg"
    new_mp3_name="$base_name.mp3"
    

    PS A rigor, as aspas acima não são necessárias, mas é uma boa prática usá-las o tempo todo, a menos que você tenha um bom motivo para não fazê-lo.
    PPS No contexto errado, pode fazer coisas como alterar para (ou seja, compactar vários espaços em um).$(echo "something")Plan  - IPlan - I

  4. Correndo o risco de ser politicamente incorreto, imagine que você é a polícia tentando solucionar um crime e que tudo o que você pode fazer é sentar do lado de fora da sede dos criminosos com um binóculo. Não seria muito melhor se você pudesse conseguir uma escuta telefônica ou um informante para saber o que estava acontecendo dentro do prédio? Depurar é como tentar resolver um crime - embora as informações externas (ou seja, a saída de zipinfoe 7za, executado separadamente) sejam importantes para entender o problema, realmente ajuda a obter as informações internas. Portanto, como uma etapa de depuração de rotina, recomendo adicionar instruções como

    printf 'cdg_name = [%s]\n' "$cdg_name" printf 'mp3_name = [%s]\n' "$mp3_name"
    

    para o script. Isso deixaria óbvio que cdg_nameestava sendo definido para a concatenação dos dois nomes e poderia ajudá-lo a rastrear para onde as I'd Do Anythingalterações I\'d Do Anything.

  5. A rigor, isso deveria ser um comentário, mas, já que estou aqui: de onde você tirou a ideia de que os nomes dos arquivos de membros contidos CB30035-05 - SIMPLE PLAN - I'D DO ANYTHING.zipestavam

    • CB30035-05 - Simple Plan - I'd Do Anything.cdg e
    • CB30035-05 - Simple Plan - I'd Do Anything.mp3

    quando você não nos mostrou nenhum comando que mostre algo entre o  Plane o  I?

  6. Como mencionei acima, I\'d Do Anythingé um quebra-cabeça. Mas você realmente tem algum exemplo de problemas relacionados a vírgulas, crases ou caracteres não ASCII (como 'é', 'Φ', 'Ø', 'θ', '½' ou '∞')?