Bash - nazwa archiwum do nazwy pliku, niewłaściwe dopasowanie (zip, cdg, mp3)
Napisałem skrypt, który sprawdza dwa konkretne rozszerzenia w archiwum zip. Przeprowadzanych jest kilka testów, które określają, czy archiwum zawiera tylko 2 pliki, a następnie je przetwarza. Jeśli archiwum ma mniej niż 2, zostanie przeniesione do folderu „ZŁE”. Jeśli archiwum ma więcej niż 2, zostanie przeniesione do katalogu „FIX”.
Etapem procesu jest wyodrębnienie plików i zmiana ich nazw na taką samą, jaką ma archiwum zip.
To wszystko działa dobrze, gdy warunki są idealne. Ale kiedy nie są idealne ... robi się brzydko.
Mam do czynienia z przypadkiem, w którym chociaż pliki mogą mieć poprawne 2 pliki i rozszerzenie, jeśli pliki mają znaki specjalne (takie jak Ø, lewy apostrof, przecinek, apostrof itp.) ... są przetwarzane (zakładam) jak składnia regex lub wyrażenia.
Oto kod:
#! /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
Wszystko w porządku, dopóki nie przejdę do zestawień mv.
mv ./"$cdg_name" ./"$new_cdg_name"
mv ./"$mp3_name" ./"$new_mp3_name"
Wydaje mi się, że być może mv może nie być właściwą metodą tutaj, ale miałem również poważne problemy ze zmianą nazwy. Myślę bardziej, że potrzebuję kodu, który mówi poleceniom, aby nie traktowały żadnych znaków w zmiennych jako czynności do wykonania.
Oto, co się dzieje ...
----- PRZYKŁAD 1 ----- NAZWA PLIKU ZIP: CB30035-05 - PROSTY PLAN - ZROBIĘ WSZYSTKO. Zip PLIKI W ZAKRESIE ZIP: CB30035-05 - Prosty plan - Zrobiłbym wszystko.cdg CB30035-05 - Prosty plan - Zrobiłbym wszystko.mp3 BŁĄD: mv: cannot stat './CB30035-05 - Simple PlanI \' d Do Anything.cdg ': Brak takiego pliku lub katalogu mv: cannot stat './CB30035-05 - Simple PlanI \' d Do Anything.mp3 ': Brak takiego pliku lub katalogu ----- PRZYKŁAD 2 ----- NAZWA PLIKU ZIP: CBSE5-0068 - STOLARZE - DLA WSZYSTKICH, KTÓRZY ZNAMY. Zip PLIKI W ZAKRESIE ZIP: cbscdge450-5-0068 - Stolarze - For All We Know.cdg cbscdge450-5-0068 - Stolarze - Dla wszystkich, co wiemy.mp3 BŁĄD: mv: cannot stat './cbscdge450-5-0068 - Carpenters - For All We Know.cdg \ ncbscdge450-5-0068 - Carpenters - For All We Know.mp3': Brak takiego pliku lub katalogu
Szukałem podobnego problemu, ale znalezione tematy nie pasowały do mojego problemu lub część kodu była nieco ponad moją głową, próbując dowiedzieć się, jak włączyć go do mojego skryptu.
Byłbym wdzięczny za każdą pomoc. Dziękuję Ci!
(UWAGA: zdaję sobie sprawę, że mój "awk" w powyższym skrypcie nic nie robi. Przeszedłem do "unzip -Z1" i wygląda na to, że rozwiązałem moje poprzednie wysiłki, aby po prostu wydobyć nazwę pliku z plików zip. go i dostosowałem tylko po to, aby zachować go na wypadek, gdyby go potrzebowałem.)
EDYCJA 2020120601:
W odpowiedzi na @Wieland usunąłem podwójną spację z nazwy pliku zip. Ale zostawił podwójną przestrzeń na plikach w środku. Nie będę w stanie naprawić wnętrza każdego pliku, ponieważ jest ich zbyt wiele, więc muszę dowiedzieć się, jak to naprawić. Usunięcie podwójnej spacji w pliku zip nie zmieniło moich wyników.
W odpowiedzi na @steeldriver, oto trochę więcej informacji. Poniżej znajduje się zwrot dla każdego polecenia, którego próbowałem użyć (zwróć uwagę, że 7za ... nie ma sposobu tylko na tworzenie nazw plików, więc wcześniej używałem awk).
Zmieniłem też kod do czytania i to nie zmieniło moich wyników, ale zgadzam się, że pokryję tę bazę.\.cdg$|\.CDG$|\.mp3$|\.MP3$
zipinfo -1 "CB30035-05 - PROSTY PLAN - ZROBIĘ WSZYSTKO.zip" CB30035-05 - Prosty plan Zrobiłbym wszystko.cdg CB30035-05 - Prosty plan Zrobię wszystko.mp3 unzip -Z1 "CB30035-05 - PROSTY PLAN - ZROBIĘ WSZYSTKO.zip" CB30035-05 - Prosty plan Zrobiłbym wszystko.cdg CB30035-05 - Prosty plan Zrobię wszystko.mp3 7za -ba l "CB30035-05 - PROSTY PLAN - ZROBIĘ WSZYSTKO.zip" 2003-06-27 14:41:56 .... A 1516512 379652 CB30035-05 - Prosty plan I'd Do Anything.cdg 2003-06-27 14:42:22 .... A 3369876 3112004 CB30035-05 - Prosty plan Zrobię wszystko.mp3
EDYCJA 2020120701:
@ G-Man mówi „Przywróć Monikę”
Dziękuję za tyle szczegółów wokół twoich wyjaśnień. Doceniam to. Będę włączał twoje sugerowane mody do skryptów. W odniesieniu do
Jeśli „zmieniłeś kod, aby czytać .cdg$|.CDG$| .mp3$|.MP3$ i to nie zmieniło moich wyników ”, to źle to zrobiłeś ...
Jestem pewien, że uważnie poszedłem za twoim przykładem. Skomentowałem, mówiąc, że to zrobiłem, ale ukośnik odwrotny został usunięty z mojej uwagi. Zaimplementowałem już również grep "c". Ale najwyraźniej poważnie brakowało opcji „i”. To zdecydowanie by to uporządkowało.
Oto kod w obecnej postaci ...
#! /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
Uwzględniłem również twoje zmiany.
Jeśli chodzi o debugowanie, po raz kolejny użyłem „echa”. To jest w moim skrypcie testowym ...
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 ""
Produkował to samo co twój "printf". Jednak bardzo lubię twoje fantazyjne sposoby i będę dostosowywał twój styl. :)
Odpowiadając na punkt 5. Wpadłem na ten pomysł korzystając z 7z.exe. Właściwie patrząc na to przez GUI. Teraz zamierzam opublikować zrzut ekranu tego, co widzi mój komputer z systemem Windows, i ponownie opublikuję, co produkuje mój komputer z systemem Linux.
WINDOWS :

LINUX :

NIE MAM POJĘCIA, dlaczego tak się dzieje. Patrząc na to przez chwilę, część mnie myśli tylko może ... Jakoś schrzaniłem swoje otoczenie. Nigdy wcześniej nie przekroczyłem tego problemu i to sprawia, że wyrywam sobie włosy!
TERAZ! Dałem ci wszystkie te informacje, a może nie dałem ci wystarczająco dużo. Ale muszę ci powiedzieć. Po wprowadzeniu zmian w kodzie generuje poprawny wynik! Mimo że mój system nadal usuwa znak „-” z nazw plików, generuje pożądany wynik końcowy. Chciałem, aby pliki przybrały nazwę pliku zip i to właśnie robi teraz.

Zmiany, które wprowadziłem ...
wyczyszczono pair_exists z
unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'
wyczyścić wyodrębnianie cdg i mp3_name oraz usunąć awk
cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$')
mp3_name=$(unzip -Z1 "$i" | grep -E -- '\.mp3$|\.MP3$')
włączył nową sugestię base_name i usunięcie echa
base_name="${zip_name%.*}"
new_cdg_name="$base_name.cdg"
new_mp3_name="$base_name.mp3"
dodano linie debugowania "printf" (zakomentuje je podczas wykonywania 150k + pliku)
printf 'cdg_name = [%s]\n' "$cdg_name"
printf 'mp3_name = [%s]\n' "$mp3_name"
Zmieniam dekompresor, aby rozpakować, aby zachować spójność z zestawem narzędzi
unzip -qq "$i"
Nie wiem, gdzie wydarzyła się poprawka, ale naprawdę doceniam twoją pomoc @ G-Man mówi „Przywróć Monikę” i pomaga mi przez to przejść i daje bardzo solidną radę.
Dziękuję Ci!
Odpowiedzi
Komentarz Steeldriver prawie na pewno identyfikuje część problemu. Jeśli „zmieniłeś kod do odczytu i to nie zmieniło moich wyników”, to zrobiłeś to źle - konkretnie, zrobiłeś to niecałkowicie. Część problemu leży w poleceniu
\.cdg$|\.CDG$|\.mp3$|\.MP3$
cdg_name=$(unzip -Z1 "$i" | grep -E -- '.cdg|.CDG' | awk '{print substr($0,index($0,$1))}')
który należy zmienić na
cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$' | awk '{print substr($0,index($0,$1))}')
ponieważ pasuje , więc ustawia się na konkatenację obu nazw , oddzielonych znakiem nowej linii. Wynika to całkiem jasno z komunikatu o błędzie.
cbscdge450-5-0068 - Carpenters …
.cdg
cdg_name
mv
Tylko dla uproszczenia możesz zmienić
unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$|\.mp3$|\.MP3$' | wc -l
do
unzip -Z1 "$i" | grep -Ec -- '\.cdg$|\.CDG$|\.mp3$|\.MP3$'
(używając opcji c ount of
grep
) lub nawetunzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'
(używając opcji i gnore case
grep
).Nie ma prawie żadnego powodu, by to powiedzieć . Właściwie jestem skłonny powiedzieć, że nigdy nie ma powodu, aby to robić, ale ktoś prawdopodobnie zidentyfikuje dziwny przypadek narożny, w którym jest to korzystne. Konkretnie,
$(echo "something")
new_cdg_name="$(echo "${zip_name%.*}.cdg")" new_mp3_name="$(echo "${zip_name%.*}.mp3")"
można zmienić na
new_cdg_name="${zip_name%.*}.cdg" new_mp3_name="${zip_name%.*}.mp3"
Mogę nawet posunąć się do zmiany ich na
base_name="${zip_name%.*}" new_cdg_name="$base_name.cdg" new_mp3_name="$base_name.mp3"
PS Ściśle mówiąc, powyższe cytaty nie są konieczne, ale dobrą praktyką jest używanie ich przez cały czas, chyba że masz dobry powód, aby tego nie robić.
PPS W złym kontekście, można zrobić takie rzeczy, jak zmiana na (tj. Skompresować wiele spacji w jedną).$(echo "something")
Plan - I
Plan - I
Ryzykując niepoprawność polityczną, wyobraź sobie, że jesteś policją próbującą rozwiązać przestępstwo i że jedyne, co możesz zrobić, to siedzieć przed siedzibą przestępców z lornetką. Czy nie byłoby o wiele lepiej, gdybyś mógł uzyskać podsłuch lub informatora, abyś mógł wiedzieć, co dzieje się w budynku? Debugowanie jest jak próba rozwiązania przestępstwa - podczas gdy informacje zewnętrzne (tj. Dane wyjściowe
zipinfo
i7za
uruchamiane osobno) są ważne dla zrozumienia problemu, to naprawdę pomaga uzyskać informacje wewnętrzne. Tak więc, jako rutynowy krok debugowania, polecam dodanie takich instrukcji jakprintf 'cdg_name = [%s]\n' "$cdg_name" printf 'mp3_name = [%s]\n' "$mp3_name"
do scenariusza. To sprawiłoby, że
cdg_name
było oczywiste, że zostało ustawione połączenie tych dwóch nazw, i może pomóc w śledzeniu, gdzieI'd Do Anything
nastąpiły zmianyI\'d Do Anything
.Ściśle rzecz biorąc, powinno to być komentarz, ale tak długo, jak jestem tutaj: skąd wziąłeś pomysł, że nazwy plików członkowskich odległości
CB30035-05 - SIMPLE PLAN - I'D DO ANYTHING.zip
byłyCB30035-05 - Simple Plan - I'd Do Anything.cdg
iCB30035-05 - Simple Plan - I'd Do Anything.mp3
kiedy nie pokazałeś nam żadnego polecenia, które pokazuje coś pomiędzy
Plan
aI
?Jak wspomniałem powyżej,
I\'d Do Anything
jest to zagadka. Ale czy rzeczywiście masz jakieś przykłady problemów związanych z przecinkami, znakami ukośnymi lub znakami spoza zestawu ASCII (np. „É”, „Φ”, „Ø”, „θ”, „½” lub „∞”)?