Existe alguma maneira de fazer com que o shell do cmd do Windows expanda os caminhos curinga?

37

Ocasionalmente, a incapacidade do shell do cmd em expandir caminhos curinga pode realmente ser um inconveniente. Eu tive que passar 100 arquivos em um diretório para um programa e não consegui digitar * .ext. Em vez disso, usei 'ls' de mingw para despejar a lista em um arquivo e substituí novas linhas por espaços, copiadas e coladas no cmd. Um pesadelo.

Suspeito que a resposta seja não, mas alguém já lidou com isso ou apresentou alguma maneira de facilitar isso?

cemitar
fonte
2
Você já pensou em usar algo como o PowerShell?
I suspect the answer will be no, but has anyone dealt with this or come up with any way to make this easier? Na verdade, estou tendo o problema oposto, estou tentando descobrir uma maneira de fazer com que o interpretador de comandos trate sua lista como seqüências de caracteres e impeça que ela os represente como curingas. Por exemplo, for %i in (foobar baz really?) do @echo %iirá tratar o último item ( really?) como um curinga nome do arquivo, e ignorá-lo se não há arquivos chamados really1, reallyzetc. ☹
Synetech
1
@ Synetech - ?não é um caractere legal para nomes de arquivos no sistema de arquivos do Windows. O personagem só pode ser interpretado como um curinga. Consulte Nomeando arquivos, caminhos e espaços para nome no MSDN e Usando caracteres curinga no TechNet.
JWW

Respostas:

18

O DOS e, consequentemente, o Windows ' cmd.exenunca suportaram expansão de curinga pelo shell. Estava sempre à disposição do aplicativo fazer a expansão.

Isso significa que você sempre terá que encontrar outra rota se estiver usando um aplicativo que não suporta expansão. Você poderia:

  • Use um loop FOR para executar alguns comandos em todos os arquivos nos quais você está interessado
  • Use dir /b > list.txtpara usar o dircomando para executar a expansão e colocar a lista de arquivos em um arquivo de texto (você poderá usar algo como uma fórmula do Excel se estiver realmente desesperado para produzir uma lista de comandos para colar cmdou usar o Excel para transpor as células para que todos os nomes de arquivos estejam na mesma linha.)
Malvineous
fonte
Ele explicou que seria um pesadelo exibir os resultados do dir em um arquivo e filtrar e copiar processos manualmente. A resposta do wmz e, claro, a minha funcionariam sem filtrar manualmente o conteúdo de um arquivo.
wullxz
1
@wullxz: Talvez, mas para alguém não familiarizado com o Powershell que queira fazer isso de uma só vez, poderia ser consideravelmente mais rápido - e a idéia por trás deste site é fornecer soluções úteis para pessoas de todos os níveis de habilidade se referirem agora e em no futuro, então realmente não há necessidade de me denunciar, porque você acha que minha resposta não é tão boa quanto a sua.
Malvineous
1
"O DOS e, consequentemente, o cmd.exe do Windows, nunca suportaram a expansão de curingas pelo shell." - Não é verdade, de acordo com a Microsoft. Consulte Usando caracteres curinga no TechNet. (Mas eu acho que você está certo na prática: o Caso contrário, eu não estaria aqui tentando descobrir por que os arquivos não são correspondidos.)
JWW
1
@jww: O link que você postou explica o uso padrão dos caracteres curinga, mas não vejo nenhuma menção a eles sendo expandidos pelo shell. Diferentemente do UNIX (e posterior Linux e Mac), a Microsoft deixou a expansão de curingas para cada aplicativo individual a ser implementado, passando os parâmetros da linha de comando como estão.
Malvineous 30/07/2015
1
O comando DOS 'dir Filespec / b' funciona muito bem, porque cria uma lista de arquivos, um por linha. Com a opção '/ s' adicional, os nomes dos arquivos são totalmente qualificados (absolutos) e podem ser facilmente alimentados através de um loop for para qualquer outro programa de linha de comando que use um nome de arquivo. É o melhor que podemos fazer, pois o Windows não possui um recurso de globbing adequado.
David A. Gray
9

Basta usar o Powershell, pré-instalado no Windows 7. O Powershell é capaz de executar comandos cmd e entende curingas em qualquer lugar do caminho.

Para iniciar o Powershell, digite "powershell" na caixa de pesquisa do menu Iniciar e pressione Enter.


Caso o aplicativo espere uma string com todos os nomes de arquivos, este é o script correto:

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

Mude $delimiter = " "para $delimiter = ","se o seu aplicativo espera uma lista separada por vírgula de nomes de arquivos.

Explicação do código:

  • [string]$files = $nothing - cria uma variável vazia do tipo string
  • ; - é um separador para vários comandos, não um pipeline!
  • ls *.txt | % { $files += $_.fullname + $delimiter } - obtém uma lista de todos os arquivos de texto e cria uma string com todos os nomes de arquivos separados pelo delimitador
  • application.exe $files - chama o aplicativo e passa a lista de arquivos para ele

Você pode até procurar um padrão de arquivo recursivamente adicionando -recursepara ls *.txtque o código completo fique assim:

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

Edit:
Para evitar irritações, lse dirsão os pseudônimos de Get-ChildIteme %é um pseudônimo para ForEach-Object. Eu mantenho meu código com aliases usados ​​porque é mais curto.

EDIT 2018/04/25:
Em 2012, sou relativamente novo no PowerShell. É claro que existe uma maneira mais fácil, embora não seja tão fácil quanto a capacidade de expansão glob do unix / linux:

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

Explicação:

  • $ () avaliará a expressão dentro primeiro e se substituirá pela saída dessa expressão (assim como os backticks fazem no bash)
  • ls *.txt obtém objetos FileInfo de todos os arquivos que correspondem ao glob *.txt
  • como o PowerShell é orientado a objetos, precisamos gerar o nome completo de cada objeto FileInfo. Simplesmente nomear um atributo / propriedade no PowerShell gera-o por padrão. % { $_.FileName }faz isso por nós. %faz um loop em todos os elementos retornados lse gera cada objeto FileName.
wullxz
fonte
2
Embora o PS certamente seja capaz de atender às solicitações e os conselhos para se familiarizar com ela sejam sólidos - não é tão simples quanto você sugere. Correndo start notepad++ *.txt(com intenção de abrir todos os arquivos de texto - bloco de notas usado ++ como ele faz lidar com vários nomes) levarão a lugar nenhum
wmz
1
Você pode contornar isso com dir *.txt | % { notepad++.exe $_ }. Eu tentei isso com o bloco de notas simples, porque não tenho o bloco de notas ++ e funcionou. O comando recebe uma lista de todos os arquivos txt no diretório atual, passa a lista para o próximo comando que percorre a lista e executa o bloco de notas ++ com o nome do arquivo como parâmetro.
wullxz
sim, mas isso não é equivalente. Pense em grep "a b c"encontrar qualquer das cordas listados, onde "ab c" seria lista expandida
wmz
5
A execução de um comando com uma lista de itens como parâmetro não é equivalente a executar o comando várias vezes com cada elemento de uma lista como parâmetro. Outro exemplo: copy a+b+c resulte copy a result copy b result copy c result. (e grep como a utilidade fazer existe no PS, ele é chamado select-string)
wmz
1
upvoted, btw é uma pena que OP não se preocupa em carrilhão para explicar ...
wmz
8

Isso fornecerá uma lista e também a colocará na variável nomeada expanded_list. Coloque-o no arquivo em lotes e execute-o com myBatchFile name myPattern. Coloque o padrão entre aspas se incluir espaços. Corresponde a arquivos, sem diretórios. Executar sem parâmetros corresponde a todos.

@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%

Você pode então executar seu comando com my_command_exec %expanded_list%

ATENÇÃO! O tamanho máximo da variável cmd é de 8191 caracteres (XP em diante), portanto, é possível transbordar! Você não pode contar com o utilitário para sempre fornecer uma lista completa. Por outro lado, o comprimento máximo da linha cmd também é 8191, portanto você não seria capaz de executá-lo de qualquer maneira.

wmz
fonte
Observe que, se nenhum argumento for especificado, o expand_list será definido para todos os arquivos no diretório atual, que podem ou não ser o que se deseja, portanto, pode adicionar verificação sem argumentos (por exemplo, se "% 1" == "" ...)
JasonM1
3

Isso funciona no cmd.exe

dir /b *.ext

ou

echo | dir /b *.ext
user619818
fonte
Isso funciona apenas para o nome do arquivo, não para qualquer parte do caminho. Por exemplo dir /b TortoiseSVN\bin\sv*.exe, mostrará svn.exee svnadmin.exe. Mas dir /b TortoiseSVN\bi*\svn.exemostra um erro de sintaxe.
Styfle 11/09/15
1
cheque dir /s /b. Isso fornece o caminho completo.
WesternGun
3

Observe que isso está em Comentário aos pôsteres em um thread separado user619818 e styfle)

O DIR pode e permite procurar em todos os subdiretórios arquivos que correspondam a um tipo específico.

Nota: O diretório raiz para verificar em que todos os subdiretórios estão é considerado "C: \ My Program \ Root \", pois o autor não forneceu um nome de caminho no qual esses diretórios estão localizados

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

isso fornecerá os caminhos e os nomes completos dos arquivos de origem.

se você quiser apenas nomes de arquivos, deverá fazer o seguinte

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

supondo que você queira mover todos esses arquivos de "C: \ Meu programa \ Raiz \ Subdiretórios \ *. ext" para "D: \ Pasta única \ *. ext", basta fazer o seguinte:

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

Espero que ajude outras pessoas no futuro. :)

Ben Personick
fonte
1

Isso é antigo, mas com o subsistema Linux para Windows, é bastante comum ter o bash no seu PATH agora. Se for esse o caso, isso pode fazer o truque para você:

bash -c 'cat *.txt'
Richard
fonte
observe que aspas simples não são especiais no cmd do Windows ; portanto, se você executar o comando acima a partir do cmd, ele não funcionará. E isso também se aplica a sistemas com Cygwin ou outros ambientes festança
phuclv