Jak mogę sprawdzić, czy argument jest zdefiniowany podczas uruchamiania / wywoływania pliku wsadowego?

97

Próbuję użyć następującej logiki sprawdzania poprawności w pliku wsadowym, ale blok „użycie” nigdy nie jest wykonywany, nawet jeśli do pliku wsadowego nie podano żadnego parametru.

if ("%1"=="") goto usage

@echo This should not execute

@echo Done.
goto :eof

:usage
@echo Usage: %0 <EnvironmentName>
exit 1

Co ja robię źle?

Daniel Fortunov
źródło
@ double-beep - Pytanie tutaj (przez daniel-fortunov) zostało zadane jako pierwsze, około rok przed opublikowaniem pytania, na które się odnosisz. Który jest (możliwy) duplikat?
Kevin Fegan
@KevinFegan, ponieważ drugie pytanie ma więcej wyświetleń i więcej odpowiedzi.
podwójny sygnał

Odpowiedzi:

147

Sprawdzanie, czy argument wiersza poleceń został ustawiony, może być [%1]==[], ale, jak wskazuje Dave Costa , również zadziała."%1"==""

Naprawiłem również błąd składni w echu użycia, aby uniknąć znaków większości i mniejszych. Ponadto exitpotrzebuje /Bargumentu, w przeciwnym razie CMD.exezakończy się.

@echo off

if [%1]==[] goto usage
@echo This should not execute
@echo Done.
goto :eof
:usage
@echo Usage: %0 ^<EnvironmentName^>
exit /B 1
Iain
źródło
18
[% 1] == [] jest lepsze niż "% 1" == "", ponieważ będzie poprawnie obsługiwać przypadek, w którym sam% 1 zawiera podwójne cudzysłowy. "% 1" == "" wyświetli komunikat "nieoczekiwany w tej chwili".
tekumara
2
Zwróć uwagę, że jeśli nie używasz argumentów wiersza poleceń, ale setzmiennych (nie znam poprawnej terminologii wsadowej), możesz zechcieć użyć, "%myvar%"==""ponieważ jeśli myvarzawiera spacje i nie jest cytowany, otrzymasz komunikat „nieoczekiwany w tym czasie ”wiadomość.
Pat
1
@Pat SET zmienne można sprawdzić za pomocą IF NOT DEFINED VarNamebloku. Również +1 dla tukushan za niestosowanie cytatów w porównaniu. Po prostu tego nie rób. Nigdy.
Fr0sT
10
"%~1"==""zadziała również i zajmie się przypadkiem, w którym% 1 ma podwójne cudzysłowy
Drakkim
8
"%~1"==""obsługuje spacje w zmiennej, podczas gdy []wersja nie.
Cookie Butter
17

Bardziej zaawansowany przykład:

⍟ nieograniczone argumenty.

⍟ istnieją w systemie plików (albo filelub directory?) Albo są generyczne string.

⍟ określ, czy jest to plik

⍟ określić jest katalogiem

bez rozszerzeń, działałoby w starszych skryptach!

minimalny kod ☺

@echo off

:pętla
      :: -------------------------- ma argument?
      if ["% ~ 1"] == [""] (
        echo zrobione.
        koniec
      )
      :: -------------------------- istnieje argument?
      jeśli nie istnieje% ~ s1 (
        echo nie istnieje
      ) else (
        echo istnieje
        jeśli istnieje% ~ s1 \ NUL (
          echo to katalog
        ) else (
          echo to plik
        )
      )
      :: --------------------------
      Zmiana
      goto loop
      
      
:koniec

pauza

✨ inne rzeczy…

■ w %~1- ~usuwa wszelkie opakowania "lub '.

■ in %~s1- stworzy ścieżkę DOS 8.3 naming, co jest fajną sztuczką pozwalającą uniknąć spacji w nazwie pliku podczas sprawdzania rzeczy (w ten sposób nie ma potrzeby zawijania zasobu większą liczbą "s.

["%~1"]==[""]„nie można być pewnym”, jeśli argument jest plikiem / katalogiem lub tylko ogólnym ciągiem znaków, więc zamiast tego wyrażenie używa nawiasów i oryginalnego niezmodyfikowanego %1(tylko bez "zawijania, jeśli istnieje ..)

jeśli nie było argumentów lub jeśli użyliśmy, shifta wskaźnik listy argumentów przekroczył ostatni, wyrażenie zostanie obliczone na [""]==[""].

■ jest to tak szczegółowe, jak możesz być bez używania większej liczby sztuczek (działałoby nawet w skryptach wsadowych systemu Windows-95 ...)

■ przykłady wykonania

zapisz to jako identifier.cmd

może zidentyfikować nieograniczoną liczbę argumentów (zwykle jesteś ograniczony do %1- %9), po prostu pamiętaj, aby zawijać argumenty cudzysłowami lub użyć nazewnictwa 8.3, lub przeciągnij i upuść je (automatycznie robi jedno z powyższych).


pozwala to na uruchamianie następujących poleceń:

identifier.cmd c:\windows i dostać

istnieć
jest katalogiem
Gotowe

identifier.cmd "c:\Program Files (x86)\Microsoft Office\OFFICE11\WINWORD.EXE" i dostać

istnieć
jest plikiem
Gotowe

⓷ i wiele argumentów (oczywiście to cała sprawa ..)

identifier.cmd c:\windows\system32 c:\hiberfil.sys "c:\pagefile.sys" hello-world

i dostać

istnieć
jest katalogiem
istnieć
jest plikiem
istnieć
jest plikiem
nie istnieje
Gotowe.

naturalnie może być dużo bardziej złożone, ale ładne przykłady zawsze powinny być proste i minimalne. :)

Mam nadzieję, że to pomoże każdemu :)

opublikowane tutaj: CMD Ninja - nieograniczone przetwarzanie argumentów, identyfikacja, czy istnieją w systemie plików, identyfikacja, czy plik lub katalog

a oto działający przykład, który pobiera dowolną ilość plików APK (aplikacji na Androida) i instaluje je na urządzeniu za pomocą konsoli debugowania (ADB.exe): Utwórz poprzedni post Masowy instalator APK, który nie używa składni ADB Install-Multi

Społeczność
źródło
14

Pozbądź się nawiasów.

Przykładowy plik wsadowy:

echo "%1"

if ("%1"=="") echo match1

if "%1"=="" echo match2

Wynik uruchomienia powyższego skryptu:

C:\>echo "" 
""

C:\>if ("" == "") echo match1 

C:\>if "" == "" echo match2 
match2

Myślę, że tak naprawdę to nawiasy są częścią ciągów i są one porównywane.

Dave Costa
źródło
1
if "%1"==""ulegnie awarii, jeśli argument ma spacje. Na przykład: run.bat "a b". @amr ma najlepszą odpowiedź do użyciaif "%~1"==""
wisbucky
6
IF "%~1"=="" GOTO :Usage

~ anuluje cudzysłów% 1, jeśli sam% 1 jest cytowany.

„” będzie chronił przed przekazanymi znakami specjalnymi. na przykład wywołanie skryptu za pomocą & ping

Amr Ali
źródło
1
To najlepsza odpowiedź. Inne odpowiedzi działają w niektórych przypadkach, ale zawiodą w bardziej szczególnych przypadkach, takich jakrun.bat "a b"
wisbucky,
@wisbucky To nie wydaje się zepsuć zaakceptowanej odpowiedzi . czego mi brakuje?
ruffin
@ruffin, przykład: run.bat ""nie zostanie złapany przez [%1]==[].
wisbucky
2
IF "%1"=="" GOTO :Continue
.....
.....
:Continue
IF "%1"=="" echo No Parameter given
Howard Rothenburg
źródło
To wywala się dlarun.bat "a b"
wisbucky
2

To jest to samo, co inne odpowiedzi, ale używa tylko jednej etykiety i stawia użycie na pierwszym miejscu, co dodatkowo sprawia, że ​​służy jako rodzaj dokumentacji pochwalającej skrypt, który również jest zwykle umieszczony na górze:

@echo off
:: add other test for the arguments here...
if not [%1]==[] goto main
:: --------------------------
echo This command does something.
echo.
echo %0 param%%1 param%%2
echo       param%%1 the file to operate on
echo       param%%1 another file

:: --------------------------
exit /B 1

:main
:: --------------------------
echo do something with all arguments (%%* == %*) here...

Jeśli jednak nie musisz używać cmd / batch, używać bash na WSL lub PowerShell, mają one bardziej rozsądną składnię i mniej tajemniczych funkcji.

masterxilo
źródło
0

JEŻELI "% 1" == "" się nie powiedzie, wszystkie wersje tego błędu będą się nie powieść w pewnych warunkach trujących znaków. Tylko JEŚLI ZDEFINIOWANE lub NIE ZDEFINIOWANE są bezpieczne

codey
źródło
if [not] defined ...nie działa z parametrami takimi jak %1. Masz przykład, gdzie if "%~1" ...nie działa?
Stephan