2014-11-18 12 views
8

posso eseguire un comando forfiles con cmd /c, come previstoforfiles senza cmd/c

 
C:\>forfiles /c "cmd /c ping /a" 
IP address must be specified. 

Tuttavia se rimuovere il cmd /c, esso non riconosce alcun argomento, solo il comando di base

 
C:\>forfiles /c "ping /a" 
Usage: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS] 
      [-r count] [-s count] [[-j host-list] | [-k host-list]] 
      [-w timeout] [-R] [-S srcaddr] [-4] [-6] target_name 

Devo usare cmd /c, anche con comandi esterni sul PERCORSO?

+0

Evitare i fastidi ei dettagli esoterici e utilizzare invece PowerShell. –

+0

@Bill_Stewart questo è per quando PowerShell è rotto http://serverfault.com/a/645113 –

risposta

13

Questa è la risposta originale. Si prega di leggere sotto la linea per un'analisi completa del problema e un modo migliore per risolverlo

Luogo due spazi tra il comando ed i suoi argomenti

forfiles /c "ping /a" 

a cura Mentre la soluzione postato funziona per la domanda OP, non è una risposta completa, in quanto vi sono alcuni casi in cui questa opzione non funziona.

Perché?

Ho iniziato a eseguire il debug delle routine di parsing dell'argomento forfiles pensando che il problema riguardi il modo in cui la stringa di comando viene analizzata e convertita per generare il comando di esecuzione finale.

No, funziona senza alcun problema

La causa del problema è nella chiamata alla funzione API CreateProcess e il modo in cui le opere di argomento parser C e come i programmatori di solito trattano gli argomenti.

forfiles chiama l'API come

CreateProcess('c:\windows\system32\ping.exe','/a', ....) 

Cioè, il nome dell'applicazione e gli argomenti ad esso. Bello e pulito, ma problematico, perché il primo argomento per l'applicazione è /a

Dov'è il problema? Nel primo argomento. La normale gestione degli argomenti in quasi tutti i programmi presuppone che il primo argomento del programma sia il programma stesso (almeno il suo nome), ovvero, argv[0] è il nome del programma.

Ma perché comportarsi in quel modo, la chiamata a CreateProcess da forfiles dovrebbe essere uno qualsiasi dei

CreateProcess('c:\windows\system32\ping.exe','ping.exe /a', ....) 
CreateProcess(NULL, 'c:\windows\system32\ping.exe /a', ....) 

Come quasi di programmazione tutti in C (e in molte più lingue che seguono la stessa convenzione) si aspetta che argv[0] (tabella valore valore argomenti prima posizione) sarà il nome del programma e (tabella valore argomenti, seconda posizione) sarà il primo argomento e, poiché questo non è il caso nei processi avviati forfiles, il primo argomento verrà ignorato perché il il primo argomento reale verrà memorizzato in argv[0], non argv[1]

Quindi, il comportamento corretto o l'errore dipenderà dal parser/lexer/tokenizer utilizzato dal programma chiamato.

  • Alcuni di loro vedranno lo spazio aggiunto come argomento adizionale che verrà memorizzato all'interno argv[0] (il tokenizzatore standard MinGW/GCC e VC comportarsi in questo modo).

  • Altri saranno rimuovere gli spazi e prendere i primi dati non vuoti come argv[0] (il caso di find)

  • qualsiasi altro comportamento che si può pensare può essere adottato dal tokenizer.

E una volta che il tokenizzatore ha terminato il suo lavoro, il programma gestirà gli argomenti e selezionare una delle

  • Ignora il primo argomento in quanto è assummed il nome del programma è in questa posizione

  • Non fare supposizioni su ciò che verrà trovato nella riga di comando e identificare l'argomento.

Quindi, la soluzione spazio non è una soluzione a prova di proiettile (grazie dbenham)

Come risolverlo?

Poiché il problema è l'ausence del nome del programma nell'argomento della riga di comando e la posizione errata dei seguenti argomenti, l'opzione migliore sembra includerla (beh, possiamo includere qualsiasi cosa da utilizzare come argv[0], ma come maggior parte dei programmi si aspettano il nome del programma ...)

forfiles /c "ping ping -a" 
forfiles /c "find find /c /v 0x220x22 @path" 
+0

Ciò ha funzionato, grazie! Man that mumb syntax –

+3

+ 1. Questo è un comportamento documentato ??? Non ho mai visto questo problema prima. – npocmaka

+0

+1, ricerca molto interessante. Ma non sempre funziona. Vedi la mia risposta. – dbenham

6

È possibile evitare CMD /C se e solo se si sta eseguendo un unico esterno di comando . Se si desidera utilizzare un comando interno o se si desidera utilizzare reindirizzamento, pipe, comando concatenazione, ecc., È necessario immettere CMD /C.

C'è qualcosa di sbagliato nel modo in cui FORFILES passa gli argomenti al comando. Come MC ND ha trovato, l'aggiunta di uno spazio aggiuntivo funziona con PING. Ma questo non sembra funzionare con tutti i comandi esterni.

Funziona con PING, FINDSTR e AIUTO:

D:\>forfiles /m test.txt /c "ping /a" 

IP address must be specified. 

D:\>forfiles /m test.txt /c "help vol" 

Displays the disk volume label and serial number, if they exist. 

VOL [drive:] 

D:\>forfiles /m test.txt /c "findstr . @path" 

line 1 

Ma non riesce per FIND - l'/ C (contare) opzione è ancora perso:

D:\>forfiles /m test.txt /c "find /c /v 0x220x22 @path" 


---------- D:\TEST.TXT 
line 1 

una scommessa più sicura sembra essere aggiungere un argomento di carattere singolo in più con un solo spazio intermedio. Ma non ho idea se funzioni per tutti i comandi esterni.

D:\>forfiles /m test.txt /c "find x /c /v 0x220x22 @path" 


---------- D:\TEST.TXT: 1 

D:\>forfiles /m test.txt /c "ping x /a" 

IP address must be specified. 

D:\>forfiles /m test.txt /c "help x vol" 

Displays the disk volume label and serial number, if they exist. 

VOL [drive:] 

D:\>forfiles /m test.txt /c "findstr x . @path" 

line 1 
+0

+1, bello, non ne ero a conoscenza. Ho eseguito il debug di 'forfiles' e incluso nella mia risposta perché si comporta in questo modo. –

Problemi correlati