Bash - имя архива и имя файла, неправильное соответствие (zip, cdg, mp3)
Я написал сценарий, который проверяет наличие двух конкретных расширений в zip-архиве. Выполняется пара проверок, которые определяют, есть ли в архиве только 2 файла, а затем обрабатывают их. Если в архиве меньше 2, он переместит архив в папку «BAD». Если в архиве больше двух, он переместит архив в каталог «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 - ПРОСТОЙ ПЛАН - Я ДЕЛАЮ НИЧЕГО. Zip ФАЙЛЫ В ZIP: CB30035-05 - Простой план - Я бы сделал что угодно.cdg CB30035-05 - Простой план - Я бы сделал что угодно.mp3 ОШИБКА: mv: cannot stat './CB30035-05 - Simple PlanI \' d Do Anything.cdg ': нет такого файла или каталога mv: cannot stat './CB30035-05 - Simple PlanI \' d Do Anything.mp3 ': нет такого файла или каталога ----- ПРИМЕР 2 ----- ИМЯ ФАЙЛА ZIP: CBSE5-0068 - ПЛОТНИКИ, - ДЛЯ ВСЕХ МЫ ЗНАЕМ.zip ФАЙЛЫ В ZIP: cbscdge450-5-0068 - Плотники - For All We Know.cdg cbscdge450-5-0068 - Плотники - Всем, что мы знаем.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 - ПРОСТОЙ ПЛАН - Я ДЕЛАЮ НИЧЕГО.zip" CB30035-05 - Простой планI'd Do Anything.cdg CB30035-05 - Простой планI'd Do Anything.mp3 разархивируйте -Z1 "CB30035-05 - ПРОСТОЙ ПЛАН - Я ДЕЛАЮ НИЧЕГО.zip" CB30035-05 - Простой планI'd Do Anything.cdg CB30035-05 - Простой планI'd Do Anything.mp3 7za -ba l "CB30035-05 - ПРОСТОЙ ПЛАН - Я ДЕЛАЮ НИЧЕГО.zip" 27.06.2003, 14:41:56 .... A 1516512 379652 CB30035-05 - Простой планI'd Do Anything.cdg 2003-06-27 14:42:22 .... A 3369876 3112004 CB30035-05 - Простой план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 $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. Собственно смотрим на это через графический интерфейс. Теперь я собираюсь опубликовать снимок экрана того, что видит мой ящик Windows, и снова я опубликую то, что производит мой ящик Linux.
ОКНА :

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" (закомментируют их при создании 150k + файла)
printf 'cdg_name = [%s]\n' "$cdg_name"
printf 'mp3_name = [%s]\n' "$mp3_name"
Я меняю декомпрессор, чтобы разархивировать, чтобы оставаться в соответствии с набором инструментов
unzip -qq "$i"
Я не знаю, где произошло исправление, но я очень признателен за вашу помощь, @ G-Man Says «Reinstate Monica», за то, что помог мне в этом и дал очень цельный совет.
Спасибо!
Ответы
Комментарий 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 опции из р а ф
grep
) или дажеunzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'
(с использованием опции i gnore case
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 (например, «é», «Φ», «Ø», «θ», «½» или «∞»)?