Ich kann einen Befehl forfiles
mit ausführen
cmd /c
, wie erwartet
Wenn ich jedoch cmd /c
lösche, erkennt es nur noch keine Argumente
der Basisbefehl
Muss ich cmd /c
verwenden, auch mit externen Befehlen im PATH?
Dies ist die ursprüngliche Antwort. Bitte lesen Sie unten die Zeile für eine vollständige Analyse des Problems und einen besseren Weg, es zu lösen
Platzieren Sie zwei Leerzeichen zwischen dem Befehl und seinen Argumenten
%Vor%bearbeitet Obwohl die veröffentlichte Lösung für die OP-Frage funktioniert, ist sie keine vollständige Antwort, da diese Option in einigen Fällen nicht funktioniert.
Warum?
Ich habe damit begonnen, die forfiles
Argumentanalyse-Routinen zu debuggen, da das Problem darin liegt, wie die Befehlszeichenfolge analysiert und konvertiert wird, um den endgültigen Ausführungsbefehl zu generieren.
Nein, es funktioniert ohne Probleme
Die Ursache des Problems liegt im Aufruf der Funktion CreateProcess
API und in der Art, wie der C-Argumentparser funktioniert und wie die Programmierer normalerweise die Argumente handhaben.
forfiles
ruft die API als
Das heißt, der Name der Anwendung und die Argumente dazu. Schön und sauber, aber problematisch, weil das erste Argument der Anwendung /a
Wo ist das Problem? Im ersten Argument. Die übliche Argumentbehandlung in fast jedem Programm setzt voraus, dass das erste Argument des Programms das Programm selbst ist (zumindest sein Name), das heißt argv[0]
ist der Programmname.
Damit es sich jedoch so verhält, sollte der Aufruf von CreateProcess
von forfiles
irgendein
Da fast jeder, der in C programmiert (und in viel mehr Sprachen, die der gleichen Konvention folgen) erwartet, dass argv[0]
(Argumente Wert Tabelle erste Position) ist der Name des Programms und argv[1]
(Argumente Wert Tabelle, zweite Position) ist das erste Argument, und da dies in forfiles
gestarteten Prozessen nicht der Fall ist, wird das erste Argument ignoriert, da das erste reelle Argument in argv[0]
, nicht argv[1]
Das korrekte Verhalten oder der Fehler hängt also vom Parser / Lexer / Tokenizer ab, der vom aufgerufenen Programm verwendet wird.
Einige von ihnen sehen den zusätzlichen Speicherplatz als zusätzliches Argument, das in argv[0]
gespeichert wird (der Standard-Tokenizer in mingw / gcc und VC verhalten sich so).
Andere entfernen die Leerzeichen und nehmen die ersten nicht leeren Daten als argv[0]
(der Fall von find
)
Jedes andere denkbare Verhalten kann vom Tokenizer übernommen werden.
Und sobald der Tokenizer seine Arbeit beendet hat, wird das Programm die Argumente behandeln und eines von
auswählenIgnoriere das erste Argument, da angenommen wird, dass sich der Programmname an dieser Position befindet.
Machen Sie keine Annahmen darüber, was in der Befehlszeile gefunden werden soll und identifizieren Sie das Argument.
Also, die Raumlösung ist keine kugelsichere Lösung (danke, Dbenham)
Wie löst man es?
Da das Problem mit dem Argument des Programmnamens im Befehlszeilenargument und der schlechten Position der folgenden Argumente zu tun hat, scheint es die beste Option zu sein, sie einzuschließen (wir können also alles einschließen, was als argv[0]
verwendet wird, aber wie die meisten Programme den Programmnamen erwarten ...)
Sie können CMD /C
nur dann vermeiden, wenn Sie einen einzelnen externen -Befehl ausführen. Wenn Sie einen internen Befehl verwenden oder Umleitung, Pipe, Befehlsverkettung usw. verwenden möchten, müssen Sie CMD /C
verwenden.
Die Art und Weise, wie FORFILES die Argumente an den Befehl weitergibt, stimmt nicht. Wie MC ND gefunden hat, funktioniert das Hinzufügen eines zusätzlichen Speicherplatzes mit PING. Aber das scheint nicht mit allen externen Befehlen zu funktionieren.
Es funktioniert mit PING, FINDSTR und HELP:
%Vor%Aber es fehlschlägt für FIND - die / C (count) -Option wird immer noch vermisst:
%Vor%Eine sicherere Wette scheint zu sein, ein zusätzliches Einzelzeichenargument mit nur einem Zwischenraum hinzuzufügen. Aber ich habe keine Ahnung, ob das für alle externen Befehle funktioniert.
%Vor%Tags und Links command-line cmd batch-file