Bash - имя архива и имя файла, неправильное соответствие (zip, cdg, mp3)

Dec 07 2020

Я написал сценарий, который проверяет наличие двух конкретных расширений в 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-файла, и это то, что он сейчас делает.

Изменения, которые я внес ...

  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 Says «Reinstate Monica», за то, что помог мне в этом и дал очень цельный совет.

Спасибо!


Ответы

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 опции из р а ф grep) или даже

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

    (с использованием опции i gnore case 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"
    

    PS Строго говоря, цитаты в приведенном выше тексте необязательны, но рекомендуется использовать их все время, если у вас нет веской причины не делать этого.
    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

    когда вы не показали нам ни одной команды, которая показывала бы что-либо между символами  Planи  I?

  6. Как я уже упоминал выше, I\'d Do Anythingэто загадка. Но есть ли у вас на самом деле примеры проблем, связанных с запятыми, обратными кавычками или символами, отличными от ASCII (например, «é», «Φ», «Ø», «θ», «½» или «∞»)?