volker-a
Goto Top

If- und else-Bedingung gleichzeitig erfüllt?

Hi,
bei der Ausführung des folgenden Skriptes:
if exist HierIstEinLeer zeichenEnthalten (
   echo if ist true
) else (
   echo else ist true
)
kommen mir Runzeln in die Stirn. Bzw. Tränen in die Augen. Dasselbe hier:
set variable=HierIstEinLeer zeichenEnthalten
if exist %variable% (
   echo if ist true
) else (
   echo else ist true
)
Ich verstehe nicht, wie if und else gleichzeitig wahr sein können. Kann mir das bitte jemand erklären?
Bin gespannt wie ein Flitzebogen!
Danke,
Volker-A

Content-Key: 213537

Url: https://administrator.de/contentid/213537

Printed on: April 24, 2024 at 07:04 o'clock

Member: Bitboy
Bitboy Aug 07, 2013 updated at 06:06:15 (UTC)
Goto Top
Hi,

Ich nehm mal an dass es daran liegt dass "exist" für Dateien und Ordner gedacht ist.
Falls du prüfen willst ob die Variable Inhalt hat kannst du das so machen

set variable=HierIstEinLeer zeichenEnthalten
if NOT "%variable%" == "" (
echo if ist true, Variable hat Inhalt
) else (

echo else ist true, Variable hat keinen Inhalt
)

pause
Member: java667
java667 Aug 07, 2013 at 06:10:18 (UTC)
Goto Top
Hi,

ich glaube du hast den Code nicht verstanden:

if exist %variable% = prüft ob die Variable die oben über set gesetzt wird existiert

danach gibt das Script ein echo Befehl aus. In deinem Fall echo if ist true. Da könnte aber auch stehen: echo Heute regnet es
Falls die Variable nicht existiert, gibt es noch eine else Bedingung. In diesem Beispiel wird aber else niemals ausgeführt, da die Variable oben ja gesetzt wird und somit immer vorhanden ist.

Somit ist das Script in seiner jetzigen Form unsinnig und taugt nicht wirklich als Beispiel.

Gruss,
Java
Member: bastla
bastla Aug 07, 2013 updated at 06:21:23 (UTC)
Goto Top
@ java667
Nur als Anmerkung: Die Existenz einer Variablen wird mit
if defined Variable
geprüft - "exist" dient, wie schon von Bitboy erwähnt, nur der Existenzprüfung von Ordnern und Dateien ..

Grüße
bastla
Member: bastla
bastla Aug 07, 2013 updated at 07:05:15 (UTC)
Goto Top
Hallo volker-A und willkommen im Forum!

Abgesehen von allen anderen Hinweisen: Da sich in Deinem überprüften String ein Leerzeichen befindet (das in Batch als Default-Trennzeichen gilt) wäre dieser String zumindest unter Anführungszeichen zu setzen - und dann bekommst Du auch nur noch das zu erwartende (außer Du hättest tatsächlich im aktuellen Pfad eine Datei/einen Ordner mit dem Namen "HierIstEinLeer zeichenEnthalten" face-wink) Ergebnis "else ist true" ...

Was willst Du eigentlich genau prüfen?

Grüße
bastla
Member: java667
java667 Aug 07, 2013 at 06:26:22 (UTC)
Goto Top
Ok, guter Hinweis. Ich hatte in Batches Variablen bisher nie auf Existenz geprüft, daher war mir nicht klar, ob exist ggf. mehr kann. Ändert aber letztlich nichts daran, das das Script etwas Sinnfrei ist und auch als Beispiel nichts taugt.
Member: Endoro
Endoro Aug 07, 2013 updated at 07:07:29 (UTC)
Goto Top
Das Interessante ist, dass sich Variable, die Leerzeichen (oder Kommas/Semikolons) im Bezeichner enthalten, nicht mit DEFINED auf Existenz überprüfen lassen. So ergibt folgender Code:
@ECHO OFF &SETLOCAL
SET "Meine Variable=true"  

IF DEFINED Meine Variable (ECHO DEFINED) ELSE ECHO NOT DEFINED
IF DEFINED "Meine Variable" (ECHO "DEFINED") ELSE ECHO NOT "DEFINED"  
ECHO %Meine Variable%
.. als Output:
NOT "DEFINED"
true
Das erste IF wird kommentar- und fehlerlos "übersprungen".

PS: es ist noch verwirrender, der folgende Code gibt als Output DEFINED aus:
@ECHO OFF &SETLOCAL
FOR %%a IN ("mein test") DO (  
	SET "$%%~a=1"  
	IF DEFINED $%%~a ECHO DEFINED
)
Falls jemand eine Erklärung hat, würde mich das sehr interessieren.
lg.
Member: AndreasHoster
AndreasHoster Aug 07, 2013 updated at 08:03:14 (UTC)
Goto Top
Es werden nicht if und else gleichzeitig ausgeführt, es sieht nur so aus.
Durch Dein Konstrukt mit dem Leerzeichen, werden die Blöcke nicht mehr als zum IF gehörend geparst.
Ausgabe ohne Leerzeichen (Code steckt in der Batch):
D:\temp>Test.cmd
D:\temp>if exist HierIstEinLeer (echo if ist true )  else (echo else ist true )
else ist true
Wie man sieht werden hier beide Codeblöcke als If/Else geparst und ebenso angezeigt.
Mit Leerzeichen:
D:\temp>Test.cmd
D:\temp>if exist HierIstEinLeer zeichenEnthalten (
D:\temp>echo if ist true
if ist true
D:\temp>echo else ist true
else ist true
Man sieht deutlich, daß für den Parser das IF Statement mit dem ( endet.
Passt ja auch zur Definition von IF:
IF EXIST filename command
Den Filenamen (HierIstEinLeer) findet er nicht, damit wird das Kommand zeichenEnthalten ( nicht ausgeführt und produziert auch keine Fehlermeldung.
Danach wird der restliche Code abgearbeitet, also folgendes:
   echo if ist true
) else (
   echo else ist true
)
Und hier wird von oben nach unten abgearbeitet, das else ignoriert, weil Befehle zwischen ) und ( wohl ignoriert werden (laut meinem Test, dokumentiert habe ich das nicht gefunden) und dann wird auch das zweite echo abgearbeitet.

Also, er macht genau das, was Du ihm sagst, daß Du der Meinung bist was anderes zu meinen, interessiert den Computer herzlich wenig.
Member: pieh-ejdsch
pieh-ejdsch Aug 07, 2013 at 08:04:06 (UTC)
Goto Top
moin Endoro,

Die Prüfung auf das Vorhandensein einer Variable hat nichts mit delayedexpansion zu tun. Der Interpreter weis ja das die Variable gesetzt wurde. Daher kannst Du in Schleifen bzw Klammern leichter auf das Prüfen von vorhandenen Variablen zugreifen im Gegensatz dazu der Zugriff auf den Inhalt dieser Variable.

Test in der CMD-Line
> for %i in (1 "2 b" 1 "2 b" 1) do @(if defined $%~i (set "$%~i=") else set "$%~i=x") & if defined $%~i (echo $%~i ist gesetzt) else echo $%~i nicht definiert  
$1 nicht definiert
$2 b nicht definiert
$1 ist gesetzt
$2 b ist gesetzt
$1 nicht definiert

> 

Gruß Phil
Member: Endoro
Endoro Aug 07, 2013 at 08:53:23 (UTC)
Goto Top
Hallo Phil,
danke für diese Ausführungen, über die ich auch noch nachdenken muss.
Was mich verwunderte war, dass dieser Code funktioniert:
for %%i in ("mein test1") do (  
	SET "$%%~i=1"  
	if defined $%%~i (echo $%%~i ist gesetzt) else echo $%%~i nicht definiert
)
, dass es dieser nicht tut, fand ich dann nicht verwunderlich:
for %%i in ("mein test1") do (  
	SET "$%%~i=1"  
	if defined $%%~i (echo $%%~i ist gesetzt) else echo $%%~i nicht definiert
	SET "$mein test2=1"  
	if defined $mein test2 (echo $mein test2 ist gesetzt) else echo $mein test2 nicht definiert
)
und das muss schon mit der anderen Erweiterung der Forschleifenparameter zusammenhängen, die ja auch irgendwie verzögert ist.
lg.
Member: Volker-A
Volker-A Aug 07, 2013 at 13:46:30 (UTC)
Goto Top
@ Bitboy, bastla, Endoro, AndreasHoster, pieh-ejdsch: Vielen Dank!
Mein Held des Tages ist AndreasHoster ;)

Ich fasse das mal zusammen:
if exist/defined + Leerzeichen geht nicht; dies gilt für
- if-getesteten ausgeschriebenen Text,
- if-getestete Variablen, deren Inhalt Leerzeichen enthält,
- if-getesteten Variablen, deren Name Leerzeichen enthält,
jeweils unter der Bedingung, dass das if-Getestete nicht von Anführungszeichen umschlossen ist.
Die if-Anweisung wird offensichtlich übersprungen.
Die in Klammern stehende else-Anweisung wird offensichtlich ebenfalls übersprungen.
Dabei wird keine Fehlermeldung ausgegeben (was ich problematisch finde).
Man kann dieses Verhalten aufdecken, indem man das Skript ohne @echo off ausführt (ich weiß nicht, wie sich dieses Tracing oder Tracking bei Batches nennt).

Nochmal vielen Dank an alle Beteiligten!
Member: bastla
bastla Aug 07, 2013 at 14:17:14 (UTC)
Goto Top
Hallo Volker-A!

Einspruch zumindest gegen
if exist/defined + Leerzeichen geht nicht; dies gilt für
- if-getesteten ausgeschriebenen Text,
- if-getestete Variablen, deren Inhalt Leerzeichen enthält,
- unter Verwendung von Anführungszeichen kannst Du sehr wohl Text (egal ob unmittelbar oder als Variableninhalt), der Leerzeichen enthält, vergleichen, auch in Bezug auf Dateinamen (mit "exist"). Auch funktioniert ein "if defined", wenn im Variableninhalt Leerzeichen vorkommen ...

... was mich übrigens nochmals auf die (schon oben gestellte) Frage zurück führt, was Du eigentlich abfragen wolltest ...

Grüße
bastla
Member: Volker-A
Volker-A Aug 07, 2013 at 19:52:11 (UTC)
Goto Top
Hallo bastla,

Danke für deinen Einspruch. Ich sehe das genauso wie du, weshalb ich "jeweils unter der Bedingung, dass das if-Getestete nicht von Anführungszeichen umschlossen ist" geschrieben hatte.

Das Problem tat sich auf, als ich eine Abfrageschleife geschrieben hatte, die einen Satz Dateien, deren Namen jeweils in derselben Variable an die Abfrage übermittelt wurden, verarbeiten sollte, wobei zunächst die Existenz der jeweiligen Datei überprüft werden sollte. Ich hatte anfänglich leichtsinnig ohne Anführungszeichen gearbeitet, was sich bei einem Test-Dateiensatz mit einfachen und kurzen Pfaden und Namen (etwa R:\1.txt usw.) nicht negativ bemerkbar gemacht hatte. Im realen Testlauf gab es aber gemischte Fälle - soll heißen: teilweise Pfade und Namen ohne Leerzeichen, teilweise welche mit. Es funktionierte also manchmal, aber manchmal eben auch nicht. Also hatte ich das Skript stückweise auseinandergenommen und dabei bemerkt, dass bei einem if-else-Test beide Bedingungen (wenn auch nur scheinbar, wie AndreasHoster so schön ausgeführt hat) true sind, wenn Leerzeichen im Testgut vorkommen.
Ich bin jetzt darauf sensibilisiert, auf Anführungszeichen zu achten. Weil ich nicht wusste, wie man Anführungszeichen aus einem String entfernt, hatte ich sie möglichst vermieden, um sie bedarfsweise einführen zu können, den String ansonsten aber ohne Anführungszeichen vorliegen zu haben. Ich habe jetzt meine Taktik geändert und benutze jetzt regelmäßig Anführungszeichen um Pfade und Namen, was auch die Arbeit mit anderen "Sonderzeichen" erleichtert, und entferne sie bedarfsweise. Dafür habe ich zwei hübsche Lösungen - übrigens hier im Forum, das mir gut gefällt - gefunden, nämlich die Ersetzung à la %variable:"=% (HowTo For Schleife mit TokenTrenner AnführungsZeichen ( double quotes as Delimiter )). Bei dem einen Beitrag hat ein gewisser bastla mitgewirkt. Der Name könnte dir bekannt vorkommen ;) Und auch schöne Grüße an pieh-ejdsch vom anderen Beitrag ;)

Nochmal Danke an alle Beteiligten!

Grüße
Volker-A
Member: bastla
bastla Aug 07, 2013 updated at 20:03:16 (UTC)
Goto Top
Hallo Volker-A!

Ich nehme grundsätzlich die Anführungszeichen nicht in die Variable auf, sondern füge sie bei der Verwendung hinzu - dann brauchen sie auch im Fall des Falles nicht entfernt zu werden face-wink - Beispiel:
set "Beispiel=HierIstEinLeer zeichenEnthalten"  
echo %Beispiel%
echo "%Beispiel%"  
Die umgebenden Anführungszeichen in der ersten Zeile dienen vor allem der klaren Abgrenzung (öfter als einmal hat schon ein irrtümlich am Ende des Strings hinzugefügtes Leerzeichen gestört) und natürlich dem "Entschärfen" von Sonderzeichen.

Grüße
bastla