Pętlowanie przez plik wsadowy tylko wtedy, gdy odpowiedź brzmi „wszystko jest w porządku”


0

Mam plik wsadowy, który przechodzi przez zawartość katalogu i kompresuje pliki w katalogu w następujący sposób;

for %%a in (c:\data\*.*) do if "%%~xa" == "" "C:\Program Files\7-Zip\7za.exe" a -tzip -mx9 "%%a.zip" "%%a"

Widząc, że używam 7zip do kompresji pliku, zwraca komunikat „wszystko jest w porządku”, jeśli pomyślnie skompresował plik, a następnie przechodzi do następnego pliku w dowolnym.

To, co chciałbym zrobić, to:

  1. Przejdź do następnego pliku tylko wtedy, gdy odpowiedź brzmi „wszystko jest w porządku”
  2. Jeśli odpowiedzią jest coś innego niż „wszystko jest w porządku”, błąd jest rejestrowany
  3. Ponieważ wystąpił błąd, próbuje ponownie skompresować plik
  4. Raz, gdy się powiedzie, tzn. „Wszystko jest w porządku”, przechodzi do następnego pliku
  5. Kroki 3 i 4 występują maksymalnie 3 razy, zanim się poddają i przejdą do następnego pliku.

Jak mogę to osiągnąć?

Odpowiedzi:


1
  • (1) i (2)

    Możesz użyć kombinacji etykiet ifi kodów zwrotnych :

    for %%a in (…) do if … "7za.exe" … "%%a" & if not %errorlevel%==0 (set z_file="%%a" & goto error)
    …
    :error
      echo Something was borked for "%z_file%"! >> Compress.log
    
  • (3)

    Możesz wywołać linię kompresji z procedury błędu:

    :error
      echo Error…
      7z…
    
  • (4) i (5)

    Teraz stajesz się skomplikowany i wykracza poza ograniczenia pliku wsadowego. Jest to możliwe, ale wymaga zaawansowanych funkcji i włamań. Procedury kompresji i błędów można umieszczać w podprogramach i wywoływać je odpowiednio. Możesz także użyć setdo utworzenia licznika (np. set /a counter=counter+1) (Jest to jeden z powodów włączenia rozszerzeń poleceń) i iflogiki (np. if %counter% leq 3 call :compress)


Dlaczego zdefiniowano poziom błędu jako zmienną, np.% Poziom błędu% ?. Dlaczego 4 byłoby skomplikowane? Myślałbym, że zakładając, że pierwszy plik nie powiedzie się przy próbie 1, spróbuje ponownie skompresować plik, a jeśli przejdzie, wróci do pętli?
PeanutsMonkey

Poziom błędu jest wbudowaną zmienną. To nie liczba powtórzeń jest złożona, to sama koncepcja; Pliki wsadowe nigdy nie były przeznaczone do zaawansowanego programowania funkcjonalnego ani do takich gałęzi logiki. Tak jak powiedziałem, można to zrobić w przeważającej części, ale nie będzie ładne i będzie wymagało użycia wielu zaawansowanych funkcji interpretera poleceń (w tym używania rozszerzeń poleceń).
Synetech

stosując if not %errorlevel%==0 (set z_file="%%a" & goto error)styl, można wykonać dodatkowe komunikaty o błędach, używając goto try2, goto lasttryi używać, aby policzyć liczbę prób. używanie call batchlabelmoże dać możliwość powrotu do miejsca, w którym zostało przerwane
SeanC

Tak, możesz to zrobić w ten sposób, jeśli nie chcesz zbyt wielu prób (spowodowałoby to duplikację kodu, ale pisanie może być nieco prostsze niż użycie licznika).
Synetech

@Synetech - Do czego służy &symbol? Przykłady, które widziałem, wydają się wykorzystywać&&
PeanutsMonkey

1

Rozszerzając odpowiedź Synetech - jest to działający skrypt:

@echo off
SETLOCAL ENABLEEXTENSIONS
set max_try=3

for %%I in (c:\data\*.*) do if "%%~xI" == "" (
    set cnt_try=0
    call :7zip "%%~I"
)
exit /B %ERL%

:7zip
set /A cnt_try+=1
"C:\Program Files\7-Zip\7za.exe" a -tzip -mx9 "%~1.zip" "%~1"
set ERL=%ERRORLEVEL%
if %ERL% NEQ 0 if %cnt_try% LEQ %max_try% (goto :7zip) else (
    echo Something was borked for "%~1"^! ^(%ERL%^) >> Compress.log
)
exit /B %ERL%

Działa dobrze dla mnie z nieco innymi warunkami (np. if "%%~xI" == ".txt")

... i nie sądzę, że użyłem żadnych hacków :)


Powinieneś wcześniej wypróbować skrypt.
Szalony

Można argumentować, że callwprowadzanie etykiety i setlocal ENABLEDELAYEDEXPANSIONfunkcje zaawansowane. BTW, dlaczego uważasz, że potrzebujesz opóźnionej ekspansji? - Nie widzę, gdzie jest używany.
Scott

@insane - teraz jest testowany.
Limer,

@scott - angielski nie jest moim językiem ojczystym. Czy to jest lepsze? ... in my opinion i didn't use any advanced functions or hacks
Limer
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.