Bash - Nome do arquivo para nome do arquivo, correspondência imprópria (zip, cdg, mp3)
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 ...
limpou o pair_exists com
unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'
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$')
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"
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"
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
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 …
.cdg
cdg_name
mv
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 mesmounzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'
(usando a opção de caso i gnore de
grep
).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 - I
Plan - I
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
zipinfo
e7za
, 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 comoprintf 'cdg_name = [%s]\n' "$cdg_name" printf 'mp3_name = [%s]\n' "$mp3_name"
para o script. Isso deixaria óbvio que
cdg_name
estava sendo definido para a concatenação dos dois nomes e poderia ajudá-lo a rastrear para onde asI'd Do Anything
alteraçõesI\'d Do Anything
.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.zip
estavamCB30035-05 - Simple Plan - I'd Do Anything.cdg
eCB30035-05 - Simple Plan - I'd Do Anything.mp3
quando você não nos mostrou nenhum comando que mostre algo entre o
Plan
e oI
?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 '∞')?