Entwerten von Sonderzeichen, die durch Dateinamen in eine Batch-Variable kommen...
Hallo, immer wieder habe ich in einer Batch Probleme mit Sonderzeichen - Leertasten an umöglichen Stellen, alle Arten von Klammern, Klammeraffen, Prozentzeichen, Ausrufezeichen, etc.
Habe hier schon mal auf Korrektur aller falschen Dateinamen auf einem Laufwerk geschrieben - der ursprüngliche Artikel dürfte aber zu alt sein, als das sich das noch wer anschaut?!
Deshalb hier noch mal - denn ich bin mir sicher, das Problem haben bzw. hatten viele und ist sicherlich gar nicht so schwer zum lösen - wenn man nur mal weiss, wie
Beispielsweise sollte untenstehende Batch NICHTS ausgeben - doch leider...
@echo off
setlocal enabledelayedexpansion
set "Basis=c:\temp"
cd /d %Basis%
echo Suche Dateien mit Zeichen, die in der Batch Probleme machen ab %Basis%...
for /f "usebackq delims=" %%a in (`"dir "\\?\%CD%\*" /b/s"`) do (
rem dc echo Teste "%%a"...
if not exist "%%a" echo Probleme mit einer Datei, in deren Namen %%a - aber dazu noch was doofes vorkommt...
)
echo Eigentlich sollte er nichts gefunden haben... doch bei kreativen Dateinamen gibt es leider sehr wohl Eintraege...
pause
Was muss man also machen bei solchen Dateinamen?
Habe hier schon mal auf Korrektur aller falschen Dateinamen auf einem Laufwerk geschrieben - der ursprüngliche Artikel dürfte aber zu alt sein, als das sich das noch wer anschaut?!
Deshalb hier noch mal - denn ich bin mir sicher, das Problem haben bzw. hatten viele und ist sicherlich gar nicht so schwer zum lösen - wenn man nur mal weiss, wie
Beispielsweise sollte untenstehende Batch NICHTS ausgeben - doch leider...
@echo off
setlocal enabledelayedexpansion
set "Basis=c:\temp"
cd /d %Basis%
echo Suche Dateien mit Zeichen, die in der Batch Probleme machen ab %Basis%...
for /f "usebackq delims=" %%a in (`"dir "\\?\%CD%\*" /b/s"`) do (
rem dc echo Teste "%%a"...
if not exist "%%a" echo Probleme mit einer Datei, in deren Namen %%a - aber dazu noch was doofes vorkommt...
)
echo Eigentlich sollte er nichts gefunden haben... doch bei kreativen Dateinamen gibt es leider sehr wohl Eintraege...
pause
Was muss man also machen bei solchen Dateinamen?
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 224606
Url: https://administrator.de/contentid/224606
Ausgedruckt am: 22.11.2024 um 09:11 Uhr
8 Kommentare
Neuester Kommentar
Hallo dctibi,
deine Probleme sollten sich mit folgender Kombination lösen lassen:
ungetestet:
Grüße
rubberman
deine Probleme sollten sich mit folgender Kombination lösen lassen:
- Zuweisung eines Variablenwertes bei ausgeschalteter verzögerter Variablenerweiterung
- Arbeiten mit dem Variablenwert bei eingeschalteter verzögerter Variablenerweiterung
ungetestet:
@echo off
setlocal DisableDelayedExpansion
for /f "delims=" %%i in ('dir /a-d /b /s "c:\temp\*"') do (
set "filename=%%i"
setlocal EnableDelayedExpansion
if not exist "!filename!" echo Dateiname "!filename!" macht Probleme.
endlocal
)
pause
rubberman
Hallo dctibi,
ich habe mal ein "C:\Temp" bei mir angelegt und eine Datei "!%&@ ^äß(1).#" hinein gelegt. Dann meinen Batchcode um eine Zeile erweitert, damit man auch sieht, was gefunden wurde.
Die Ausgabe:
Ich kann deinen Einwand leider nicht nachvollziehen.
Grüße
rubberman
ich habe mal ein "C:\Temp" bei mir angelegt und eine Datei "!%&@ ^äß(1).#" hinein gelegt. Dann meinen Batchcode um eine Zeile erweitert, damit man auch sieht, was gefunden wurde.
@echo off
setlocal DisableDelayedExpansion
for /f "delims=" %%i in ('dir /a-d /b /s "c:\temp\*"') do (
set "filename=%%i"
setlocal EnableDelayedExpansion
echo "!filename!" wird verarbeitet.
if not exist "!filename!" echo Dateiname "!filename!" macht Probleme.
endlocal
)
pause
Die Ausgabe:
"c:\temp\!%&@ ^äß(1).#" wird verarbeitet.
Drücken Sie eine beliebige Taste . . .
Ich kann deinen Einwand leider nicht nachvollziehen.
Grüße
rubberman
Hallo dctibi,
ich habe mir vor einigen Jahren in einem masochistischen Anfall selbst eine Aufgabe gestellt, deren Problematik in die gleiche Richtung ging: Einen Fileselector in native Batch. Den Code habe ich später mal in diesem Thread gepostet (mein zweiter Kommentar dort). Ich konnte das Problem damals mit viel Mühe und Tricksereien lösen.
Der Code ist jetzt ca. 6 Jahre alt, ich kann Dir keine Einzelheiten mehr dazu erläutern, evtl. kannst Du Dir zumindest Anregungen herausziehen.
Was mir dazu noch im Gedächtnis geblieben ist:
Zeile 9 muss genau so notiert werden, damit man die veränderten Werte von x und y nach diesem Block wieder zur Verfügung hat.
Für dieses Problem gibt es leider keine allgemeingültige Antwort, da die Wahl der Mittel stark davon abhängt, in welchem Kontext man was erreichen möchte.
Viel Erfolg bei Deinen Versuchen
Friemler
[Edit]
BTW: Die folgende Sammlung von Dateinamen
lässt sich mit diesem Batchscript ausgeben:
[/Edit]
ich habe mir vor einigen Jahren in einem masochistischen Anfall selbst eine Aufgabe gestellt, deren Problematik in die gleiche Richtung ging: Einen Fileselector in native Batch. Den Code habe ich später mal in diesem Thread gepostet (mein zweiter Kommentar dort). Ich konnte das Problem damals mit viel Mühe und Tricksereien lösen.
Der Code ist jetzt ca. 6 Jahre alt, ich kann Dir keine Einzelheiten mehr dazu erläutern, evtl. kannst Du Dir zumindest Anregungen herausziehen.
Was mir dazu noch im Gedächtnis geblieben ist:
- Ich habe so weit wie möglich versucht, auf die verzögerte Variablenerweiterung zu verzichten, da man dann zwar alle "üblichen Problemkandidaten" vom Hals hat, dafür aber mit dem Ausrufezeichen kämpfen muss.
- Wenn die verzögerte Variablenerweiterung ausgeschaltet ist, kann der Inhalt von Laufvariablen der
FOR
-Schleife mitECHO
ausgegeben werden, in einer anderenFOR
-Schleife benutzt werden, als Argument an einen Befehl übergeben werden usw. Sonderzeichen werden dann brav übernommen. - Probleme tauchen auf, sobald man den Inhalt einer
FOR
-Laufvariablen, die Sonderzeichen enthält, an eine normale Umgebungsvariable zuweist und damit irgendwelche Operationen ausführen möchte. - Probleme gibt es auch, wenn man den Inhalt einer
FOR
-Laufvariablen an ein Unterprogramm übergeben will, und die Variable das Zeichen^
enthält. Im Unterprogramm wird daraus^^
. - Man kann aus einer
FOR
-Schleife ein Unterprogramm aufrufen und die Laufvariable der Schleife aus dem Hauptprogramm in einerFOR
-Schleife im Unterprogramm verwenden (lässt sich mit Punkt 2 kombinieren). - Man kann in einer
FOR
-Schleife die Laufvariable an eine normale Umgebungsvariable zuweisen und dann ein Unterprogramm aufrufen, in dem die Umgebungsvariable aus derFOR
-Schleife im Hauptprogramm den aktuellen (vorher zugewiesenen Wert) hat. Damit kann man die (normale) "sofortige" Variablenerweiterung des Batch-Interpreters austricksen. - Ich musste manchmal Abschnitte in den Code einbauen, in denen ich die verzögerte Variablenerweiterung temporär eingeschaltet habe (mit
setlocal enabledelayedexpansion
). Um am Ende eines solchen Abschnitts die geänderten Werte von Variablen aus diesem Abschnitt herauszubekommen, muss man folgendes Konstrukt verwenden:
set "x=Wert1_von_x"
set "y=Wert1_von_y"
setlocal enabledelayedexpansion
.
.
.
set "x=Wert2_von_x"
set "y=Wert2_von_y"
endlocal & set "x=%x%" & set "y=%y%"
Für dieses Problem gibt es leider keine allgemeingültige Antwort, da die Wahl der Mittel stark davon abhängt, in welchem Kontext man was erreichen möchte.
Viel Erfolg bei Deinen Versuchen
Friemler
[Edit]
BTW: Die folgende Sammlung von Dateinamen
!Hallo!.TXT
!Hallo&Welt!.TXT
!Hallo.TXT
%Hallo^&^,;_^~'^Welt&&&.TXT
&^^&%%Hall!o^^^&W%elt&^&^^&&^^.TXT
^!Hallo^&Welt%%^^.TXT
Hallo%Welt.TXT
@echo off & setlocal
set "Basis=E:\Test"
cd /d "%Basis%"
for /f "delims=" %%a in ('dir /s /b "%CD%\*"') do (
echo %%a
)
Hallo dctibi.
Auch Leerzeichen am Ende des Dateinamens führen bei mir unter keinen getesteten Umständen zum Fehlschlag. Vielleicht magst du ja doch noch das eine oder andere Beispiel zeigen, bei dem du Probleme hast. Ich bin überzeugt es lässt sich lösen, solang nicht der Unicode-Zeichensatz angezogen werden müsste um die Dateinamen zu verarbeiten.
Was das Delayed Expansion angeht, so ist das erst einmal ganz einfach erklärt (darin bin ich geübt, hatte ich letzthin erst getan). Ich zitiere mich also mal selbst
Das
In einer Kommandozeile oder einem in Klammern eingefassten Block von Kommandozeilen (zB. in einer FOR Schleife) werden normale Umgebungsvariablen nur einmal zum Wert aufgelöst, und zwar noch bevor die Zeile/der Block ausgeführt wird. Das EnableDelayedExpansion verzögert diese Auflösung, sodass die Werte zur Laufzeit der Zeile/des Blocks abgreifbar sind. Die umschließenden Prozentzeichen für die Variable sind dabei durch Ausrufezeichen zu ersetzen.
Beispiel zur Verdeutlichung:
Ende des Zitats.
Nun hat die verzögerte Erweiterung aber noch ein paar Sideeffects. Ausrufezeichen werden (sofern sie nicht maskiert wurden) bei Wertzuweisungen mal eben eliminiert. Schlimmer wird es noch, wenn ein String in Ausrufezeichen eingefasst ist, dann wird versucht diesen als Variable zu interpretieren. Das ist der Grund, warum die Zuweisung des Wertes bei ausgeschalteter verzögerter Variablenerweiterung erfolgen sollte, nach Schema
Die Anführungszeichen nicht vergessen, sonst gibt's wahrscheinlich unangenehme Überaschungen bei Sonderzeichen.
Warum dann aber für die Ausgabe/Verarbeitung einschalten? Ein Grund steht schon oben: Innerhalb der Schleife lässt sich die Variable sonst nicht zum Wert auflösen. Ein weiterer Aspekt ist, dass auch Sonderzeichen auf diese Art gefahrlos verarbeitet werden können, da diese für den Kommandozeileninterpreter beim Parsen des Codes noch nicht sichtbar sind.
Wie der Kommandozeileninterpreter mit Batchcode umgeht, lässt sich dort nachlesen.
Grüße
rubberman
Auch Leerzeichen am Ende des Dateinamens führen bei mir unter keinen getesteten Umständen zum Fehlschlag. Vielleicht magst du ja doch noch das eine oder andere Beispiel zeigen, bei dem du Probleme hast. Ich bin überzeugt es lässt sich lösen, solang nicht der Unicode-Zeichensatz angezogen werden müsste um die Dateinamen zu verarbeiten.
Was das Delayed Expansion angeht, so ist das erst einmal ganz einfach erklärt (darin bin ich geübt, hatte ich letzthin erst getan). Ich zitiere mich also mal selbst
Das
setlocal EnableDelayedExpansion
schaltet die verzögerte Variablenerweiterung ein.In einer Kommandozeile oder einem in Klammern eingefassten Block von Kommandozeilen (zB. in einer FOR Schleife) werden normale Umgebungsvariablen nur einmal zum Wert aufgelöst, und zwar noch bevor die Zeile/der Block ausgeführt wird. Das EnableDelayedExpansion verzögert diese Auflösung, sodass die Werte zur Laufzeit der Zeile/des Blocks abgreifbar sind. Die umschließenden Prozentzeichen für die Variable sind dabei durch Ausrufezeichen zu ersetzen.
Beispiel zur Verdeutlichung:
@echo off
setlocal
set "n=vorher"
for /l %%i in (0 1 4) do (
set "n=%%i"
echo %n%
)
endlocal
echo ~~~~~~~~~
setlocal EnableDelayedExpansion
set "n=vorher"
for /l %%i in (0 1 4) do (
set "n=%%i"
echo !n!
)
endlocal
pause
Nun hat die verzögerte Erweiterung aber noch ein paar Sideeffects. Ausrufezeichen werden (sofern sie nicht maskiert wurden) bei Wertzuweisungen mal eben eliminiert. Schlimmer wird es noch, wenn ein String in Ausrufezeichen eingefasst ist, dann wird versucht diesen als Variable zu interpretieren. Das ist der Grund, warum die Zuweisung des Wertes bei ausgeschalteter verzögerter Variablenerweiterung erfolgen sollte, nach Schema
SET "Variablenname=Wert"
Die Anführungszeichen nicht vergessen, sonst gibt's wahrscheinlich unangenehme Überaschungen bei Sonderzeichen.
Warum dann aber für die Ausgabe/Verarbeitung einschalten? Ein Grund steht schon oben: Innerhalb der Schleife lässt sich die Variable sonst nicht zum Wert auflösen. Ein weiterer Aspekt ist, dass auch Sonderzeichen auf diese Art gefahrlos verarbeitet werden können, da diese für den Kommandozeileninterpreter beim Parsen des Codes noch nicht sichtbar sind.
Wie der Kommandozeileninterpreter mit Batchcode umgeht, lässt sich dort nachlesen.
Grüße
rubberman