für Dateien ohne cmd / c

8

Ich kann einen Befehl forfiles mit ausführen cmd /c , wie erwartet

%Vor%

Wenn ich jedoch cmd /c lösche, erkennt es nur noch keine Argumente der Basisbefehl

%Vor%

Muss ich cmd /c verwenden, auch mit externen Befehlen im PATH?

    
Steven Penny 18.11.2014, 08:01
quelle

2 Antworten

13

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

auf %Vor%

Das heißt, der Name der Anwendung und die Argumente dazu. Schön und sauber, aber problematisch, weil das erste Argument der Anwendung /a

ist

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

sein %Vor%

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]

gespeichert wird

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ählen
  • Ignoriere 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 ...)

%Vor%     
MC ND 18.11.2014, 08:55
quelle
6

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%     
dbenham 18.11.2014 23:26
quelle

Tags und Links