C'è un modo per ottenere la shell cmd di Windows per espandere i percorsi jolly?


37

Occasionalmente, l'incapacità della shell cmd di espandere i percorsi jolly può davvero essere un inconveniente. Ho dovuto passare 100 file in una directory a un programma e non sono riuscito a digitare * .ext. Invece, ho usato 'ls' di mingw per scaricare l'elenco in un file, quindi ho sostituito le nuove righe con spazi, copiato e incollato in cmd. Piuttosto un incubo.

Sospetto che la risposta sarà no, ma qualcuno ha affrontato questo problema o ha escogitato un modo per renderlo più semplice?


2
Hai preso in considerazione l'utilizzo di qualcosa come Powershell invece?

I suspect the answer will be no, but has anyone dealt with this or come up with any way to make this easier? In realtà, sto avendo il problema opposto, sto cercando di trovare un modo per convincere l'interprete dei comandi a trattare il suo elenco come stringhe e impedirgli di rimpiazzarle come caratteri jolly. Ad esempio, for %i in (foobar baz really?) do @echo %itratterà l'ultimo elemento ( really?) come carattere jolly nome del file, e saltare se non ci sono file denominati really1, reallyzecc ☹
Synetech

1
@Synetech - ?non è un carattere legale per i nomi di file nel filesystem di Windows. Il personaggio può essere interpretato solo come un jolly. Vedere Denominazione di file, percorsi e spazi dei nomi su MSDN e Utilizzo di caratteri jolly in TechNet.
jww

Risposte:


18

DOS, e di conseguenza Windows ' cmd.exe, non ha mai supportato l'espansione jolly dalla shell. Spetta sempre all'applicazione fare l'espansione.

Ciò significa che dovrai sempre trovare un altro percorso se stai utilizzando un'applicazione che non supporta l'espansione. Potresti:

  • Usa un ciclo FOR per eseguire alcuni comandi su tutti i file che ti interessano
  • Utilizzare dir /b > list.txtper utilizzare il dircomando per eseguire l'espansione e inserire l'elenco di file in un file di testo (è quindi possibile utilizzare qualcosa come una formula di Excel se si è davvero alla disperata ricerca di un elenco di comandi in cui incollare cmd, oppure è possibile utilizzare Excel per trasporre le celle in modo che tutti i nomi dei file siano sulla stessa riga.)

Spiegò che sarebbe stato un incubo l'output dei risultati di dir in un file ed elaborare manualmente il filtro e la copia. La risposta di wmz e ovviamente la mia funzionerebbe senza filtrare manualmente il contenuto di un file.
wullxz,

1
@wullxz: Forse, ma per qualcuno che non ha familiarità con Powershell che vuole farlo come una tantum, potrebbe essere considerevolmente più veloce - e l'idea alla base di questo sito è di fornire soluzioni utili a persone di tutti i livelli di abilità a cui fare riferimento ora e in il futuro, quindi davvero non c'è bisogno di dirmi perché pensi che la mia risposta non sia buona come la tua.
Malvineous,

1
"DOS, e di conseguenza cmd.exe di Windows, non ha mai supportato l'espansione jolly dalla shell." - Non vero secondo Microsoft. Vedere Utilizzo di caratteri jolly su TechNet. (Ma penso che tu abbia ragione nella pratica: o. Altrimenti, non sarei qui a cercare di capire perché i file non sono abbinati)
jww

1
@jww: il link che hai pubblicato spiega l'uso standard dei caratteri jolly, ma non riesco a vedere alcuna menzione del loro ampliamento da parte della shell. A differenza di UNIX (e successivamente di Linux e Mac), Microsoft ha lasciato l'espansione jolly fino a ciascuna singola applicazione da implementare, passando i parametri della riga di comando così com'è.
Malvineous,

1
Il comando DOS 'dir Filespec / b' funziona davvero bene, perché crea un elenco di file, uno per riga. Con l'opzione '/ s' aggiuntiva, i nomi dei file sono pienamente qualificati (assoluti) e possono essere facilmente inseriti attraverso un ciclo for verso qualsiasi altro programma da riga di comando che accetta un nome file. È il meglio che possiamo fare, dal momento che Windows non ha una funzione di globbing adeguata.
David A. Gray,

9

Basta usare Powershell, che è preinstallato su Windows 7. Powershell è in grado di eseguire comandi cmd e comprende caratteri jolly in qualsiasi punto di un percorso.

Per avviare Powershell basta digitare "powershell" nella casella di ricerca del menu Start e premere invio.


Nel caso in cui l'applicazione si aspetti una stringa con tutti i nomi dei file, questo è lo script giusto:

$delimiter = " "
[string]$files = $nothing ; ls *.txt | % { $files += $_.fullname + $delimiter } ; application.exe $files

Passare $delimiter = " "a $delimiter = ","se l'applicazione prevede un elenco separato da virgole di nomi di file.

Spiegazione del codice:

  • [string]$files = $nothing - crea una variabile vuota di tipo string
  • ; - è un separatore per più comandi, non una pipeline!
  • ls *.txt | % { $files += $_.fullname + $delimiter } - ottiene un elenco di tutti i file di testo e crea una stringa con tutti i nomi di file separati dal delimitatore
  • application.exe $files - chiama l'applicazione e gli passa l'elenco dei file

Puoi anche cercare ricorsivamente un modello di file aggiungendolo -recursea in ls *.txtmodo che il codice completo sia simile al seguente:

$delimiter = " "
[string]$files = $nothing ; ls *.txt -recurse | % { $files += $_.fullname + $delimiter } ; application.exe $files

Modifica:
per evitare irritazioni lse diralias di Get-ChildItemed %è un alias di ForEach-Object. Tengo il mio codice con gli alias usati perché è più corto.

EDIT 2018/04/25:
Nel 2012 sono stato abbastanza nuovo in PowerShell. Naturalmente c'è un modo più semplice anche se non è facile come la capacità di espansione glob di unix / linux:

app.exe $(ls *.txt | % {$_.FullName})

Spiegazione:

  • $ () valuterà prima l'espressione all'interno e si sostituirà con l'output di quell'espressione (proprio come fanno i backtick in bash)
  • ls *.txt ottiene gli oggetti FileInfo di tutti i file che corrispondono al glob *.txt
  • poiché PowerShell è orientato agli oggetti, dobbiamo generare il nome completo di ogni oggetto FileInfo. È sufficiente assegnare un nome a un attributo / proprietà in PowerShell per impostazione predefinita. % { $_.FileName }lo fa per noi. %esegue il ciclo su tutti gli elementi restituiti da lse genera ogni oggetto FileName.

2
Anche se PS è sicuramente in grado di soddisfare le richieste e il consiglio di familiarizzare con esso è valido - non è così semplice come suggerisci. Esecuzione start notepad++ *.txt(con l'intenzione di aprire tutti i file di testo - blocco note usato ++ come fa gestire più nomi) si arriva da nessuna parte
wmz

1
Potresti risolvere il problema con dir *.txt | % { notepad++.exe $_ }. L'ho provato con un semplice blocco note, perché non ho Notepad ++, e ha funzionato. Il comando riceve un elenco di tutti i file txt nella directory corrente, passa l'elenco al comando successivo che scorre attraverso l'elenco ed esegue notepad ++ con il nome file come parametro.
Wullxz,

si, ma questo non è equivalente. Pensa grep "a b c"di trovare una qualsiasi delle stringhe elencate, dove "ab c" sarebbe espanso elenco
wmz

5
L'esecuzione di un comando con un elenco di elementi come parametro non equivale a eseguire il comando più volte con ciascun elemento di un elenco come parametro. Un altro esempio: copy a+b+c resulte copy a result copy b result copy c result. (e grep come l'utilità esiste in PS, si chiama select-string)
wmz,

1
votato, tra l'altro è un peccato che OP non si preoccupi di intervenire per spiegare ...
wmz

8

Questo ti darà un elenco e lo metterà anche nella variabile denominata expanded_list. Mettilo in un file batch ed eseguilo con myBatchFile name myPattern. Racchiudere il motivo tra virgolette se include spazi. Corrisponde ai file, nessuna directory. Esegui senza parametri corrisponde a tutti.

@echo off
set expanded_list=
for /f "tokens=*" %%F in ('dir /b /a:-d "%~1"') do call set expanded_list=%%expanded_list%% "%%F"

echo expanded_list is: 
echo %expanded_list%

È quindi possibile eseguire il comando con my_command_exec %expanded_list%

AVVERTIMENTO! La dimensione massima della variabile cmd è di 8191 caratteri (XP in poi), quindi è possibile traboccare! Non puoi contare sull'utilità per darti sempre un elenco completo. D'altra parte, anche la lunghezza massima della linea cmd è 8191, quindi non saresti in grado di eseguirla comunque.


Nota se non viene specificato alcun argomento, la lista espansa verrà impostata su tutti i file nella directory corrente, che potrebbe essere o meno ciò che si desidera, quindi potrebbe essere necessario aggiungere un controllo per nessun argomento (ad es. Se "% 1" == "" ...)
JasonM1,

3

Funziona in cmd.exe

dir /b *.ext

o

echo | dir /b *.ext

Funziona solo per il nome del file, non per qualsiasi parte del percorso. Ad esempio dir /b TortoiseSVN\bin\sv*.exemostrerà svn.exee svnadmin.exe. Ma dir /b TortoiseSVN\bi*\svn.exemostra un errore di sintassi.
Styfle,

1
controllare dir /s /b. Questo ti dà il percorso completo.
WesternGun

3

Nota, questo è nel commento ai poster in un thread separato user619818 e styfle)

DIR può e consente di cercare in tutte le sottodirectory i file corrispondenti a un tipo specifico.

Nota: si presume che la directory principale per verificare in quale sotto tutte le sottodirectory sia "C: \ My Program \ Root \" poiché l'autore non ha assegnato un nome di percorso in cui si trovano queste directory

DIR /B /S "C:\My Program\Root\*.ext"

questo fornirà i percorsi e i nomi file completi dei file sorgente.

se vuoi solo nomi di file dovresti fare come segue

FOR /F "Tokens=*" %A IN ('DIR /B /S "C:\My Program\Root\*.ext"') DO @( Echo.%~nxA )

quindi supponendo che tu voglia spostare tutti questi file da "C: \ My Program \ Root \ Sub Directories \ *. ext" a "D: \ Singlefolder \ *. ext" fai semplicemente questo:

FOR /F "Tokens=*" %A IN ('DIR /B /S "C:\My Program\Root\*.ext"') DO @( MOVE "%~A" "D:\Singlefolder\%~nxA" /Y )

Spero che aiuti gli altri in futuro. :)


1

Questo è vecchio, ma con il sottosistema Linux per Windows, è abbastanza comune avere bash nel tuo PERCORSO ora. In tal caso, questo potrebbe fare al caso tuo:

bash -c 'cat *.txt'

notare che le virgolette singole non sono speciali in Windows cmd , quindi se si esegue il comando sopra da cmd non funzionerà. E questo vale anche per i sistemi con Cygwin o altri ambienti bash
phuclv,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.