Wie kann ich überprüfen, ob beim Starten / Aufrufen einer Batchdatei ein Argument definiert ist?

95

Ich versuche, die folgende Validierungslogik in einer Batchdatei zu verwenden, aber der Block "usage" wird nie ausgeführt, selbst wenn der Batchdatei kein Parameter angegeben wird.

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

@echo This should not execute

@echo Done.
goto :eof

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

Was mache ich falsch?

Daniel Fortunov
quelle

Antworten:

145

Die Prüfung auf , ob ein Kommandozeilen - Argument kann eingestellt wurde sein [%1]==[], aber, wie Dave Costa weist darauf hin , "%1"==""wird auch funktionieren.

Ich habe auch einen Syntaxfehler im Verwendungsecho behoben, um den Zeichen größer als und kleiner als zu entkommen. Darüber hinaus wird die exitNotwendigkeit eines /BArguments ansonsten CMD.exebeendet.

@echo off

if [%1]==[] goto usage
@echo This should not execute
@echo Done.
goto :eof
:usage
@echo Usage: %0 ^<EnvironmentName^>
exit /B 1
Iain
quelle
18
[% 1] == [] ist besser als "% 1" == "", da es den Fall korrekt behandelt, in dem% 1 selbst doppelte Anführungszeichen enthält. "% 1" == "" wird mit der Meldung "Zu diesem Zeitpunkt unerwartet" fehlerhaft angezeigt.
Tekumara
2
Beachten Sie, dass Sie, wenn Sie keine Befehlszeilenargumente, sondern setVariablen verwenden (ich kenne die richtige Batch-Terminologie nicht), diese möglicherweise verwenden möchten, "%myvar%"==""da myvarSie zu diesem Zeitpunkt das "Unerwartete" erhalten, wenn Leerzeichen darin sind und nicht in Anführungszeichen gesetzt werden " Botschaft.
Pat
1
@ Pat SET-Variablen können mit IF NOT DEFINED VarNameBlock überprüft werden . Auch +1 nach Tukushan, weil im Vergleich keine Anführungszeichen verwendet werden. Tu es einfach nicht. Noch nie.
Fr0sT
10
"%~1"==""wird auch funktionieren und sich um den Fall kümmern, in dem% 1 doppelte Anführungszeichen hat
Drakkim
8
"%~1"==""behandelt Leerzeichen in der Variablen, während die []Version dies nicht tut.
Keks-Butter
17

Ein fortgeschritteneres Beispiel:

⍟ unbegrenzte Argumente.

⍟ existieren im Dateisystem (entweder fileoder directory?) Oder in einem generischen string.

⍟ Geben Sie an, ob es sich um eine Datei handelt

⍟ angeben ist ein Verzeichnis

Keine Erweiterungen, würde in Legacy-Skripten funktionieren!

Minimaler Code ☺

@echo aus

:Schleife
      :: -------------------------- hat Argument?
      if ["% ~ 1"] == [""] (
        Echo fertig.
        gehe zum Ende
      )
      :: -------------------------- Argument vorhanden?
      falls nicht vorhanden% ~ s1 (
        Echo existiert nicht
      ) else (
        Echo vorhanden
        falls vorhanden% ~ s1 \ NUL (
          Echo ist ein Verzeichnis
        ) else (
          Echo ist eine Datei
        )
      )
      :: --------------------------
      Verschiebung
      gehe zur Schleife
      
      
:Ende

Pause

✨ andere Sachen..✨

■ in %~1- das ~entfernt jegliche Umhüllung "oder '.

■ in %~s1- das smacht den Pfad DOS 8.3 naming, was ein guter Trick ist, um Leerzeichen im Dateinamen zu vermeiden, während Dinge überprüft werden (und auf diese Weise muss die Ressource nicht mit mehr "s umbrochen werden .

■ das ["%~1"]==[""]"kann nicht sicher sein", ob das Argument noch eine Datei / ein Verzeichnis oder nur eine generische Zeichenfolge ist. Stattdessen verwendet der Ausdruck Klammern und das Original unverändert %1(nur ohne "Umbruch, falls vorhanden).

Wenn es keine Argumente dafür gab, ob wir verwendet haben shiftund der Zeiger auf die Argumentliste den letzten übergeben hat, wird der Ausdruck ausgewertet [""]==[""].

■ Dies ist so spezifisch, wie Sie es können, ohne weitere Tricks zu verwenden (es würde sogar in den Batch-Skripten von Windows-95 funktionieren ...)

■ Ausführungsbeispiele

Speichern Sie es als identifier.cmd

Es kann eine unbegrenzte Anzahl von Argumenten identifizieren (normalerweise sind Sie auf %1- beschränkt %9). Denken Sie jedoch daran, die Argumente mit Anführungszeichen zu versehen oder die 8.3-Benennung zu verwenden oder sie per Drag & Drop zu verschieben (dies geschieht automatisch oben).


Auf diese Weise können Sie die folgenden Befehle ausführen:

identifier.cmd c:\windows und zu bekommen

existieren
ist ein Verzeichnis
getan

identifier.cmd "c:\Program Files (x86)\Microsoft Office\OFFICE11\WINWORD.EXE" und zu bekommen

existieren
ist eine Datei
getan

⓷ und mehrere Argumente (das ist natürlich die ganze Sache ..)

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

und zu bekommen

existieren
ist ein Verzeichnis
existieren
ist eine Datei
existieren
ist eine Datei
nicht existieren
getan.

Natürlich kann es viel komplexer sein, aber schöne Beispiele sollten immer einfach und minimal sein. :) :)

Hoffe es hilft jedem :)

hier veröffentlicht: CMD Ninja - Unbegrenzte Argumentverarbeitung, Identifizieren, ob im Dateisystem vorhanden, Identifizieren, ob Datei oder Verzeichnis

und hier ist ein funktionierendes Beispiel, das eine beliebige Anzahl von APK-Dateien (Android-Apps) verwendet und über die Debug-Konsole (ADB.exe) auf Ihrem Gerät installiert: Machen Sie den vorherigen Beitrag zu einem Massen-APK-Installationsprogramm, das keine ADB Install-Multi-Syntax verwendet

Gemeinschaft
quelle
14

Entfernen Sie die Klammern.

Beispiel-Batch-Datei:

echo "%1"

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

if "%1"=="" echo match2

Ausgabe von oben ausgeführtem Skript:

C:\>echo "" 
""

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

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

Ich denke, es braucht tatsächlich die Klammern, um Teil der Zeichenfolgen zu sein, und sie werden verglichen.

Dave Costa
quelle
1
if "%1"==""stürzt ab, wenn das Argument Leerzeichen enthält. Zum Beispiel : run.bat "a b". @amr hat die beste Antwort zu verwendenif "%~1"==""
wisbucky
6
IF "%~1"=="" GOTO :Usage

~ wird% 1 dekotieren, wenn% 1 selbst in Anführungszeichen gesetzt wird.

"" schützt vor übergebenen Sonderzeichen. Zum Beispiel das Skript mit & ping aufrufen

Amr Ali
quelle
1
Dies ist die beste Antwort. Die anderen Antworten funktionieren in einigen Fällen, scheitern jedoch in besonderen Fällen wierun.bat "a b"
wisbucky
@wisbucky Das scheint die akzeptierte Antwort nicht durcheinander zu bringen . Was vermisse ich?
Ruffin
@ Ruffin, Beispiel: run.bat ""wird nicht mit gefangen [%1]==[].
wisbucky
2
IF "%1"=="" GOTO :Continue
.....
.....
:Continue
IF "%1"=="" echo No Parameter given
Howard Rothenburg
quelle
Dies stürzt fürrun.bat "a b"
wisbucky
2

Dies ist dasselbe wie bei den anderen Antworten, verwendet jedoch nur ein Etikett und stellt die Verwendung an die erste Stelle, wodurch es zusätzlich als eine Art Dokumentationsempfehlung für das Skript dient, das normalerweise auch oben platziert wird:

@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...

Wenn Sie jedoch nicht cmd / batch, bash für WSL oder Powershell verwenden müssen, verfügen sie über eine vernünftigere Syntax und weniger arkane Funktionen.

masterxilo
quelle
0

WENN "% 1" == "" fehlschlägt, schlagen alle Versionen unter bestimmten Bedingungen für Giftcharaktere fehl. Nur WENN DEFINIERT oder WENN NICHT DEFINIERT, sind sicher

Codey
quelle
if [not] defined ...funktioniert nicht mit Parametern wie %1. Haben Sie ein Beispiel, wo if "%~1" ...es nicht funktioniert?
Stephan