¿Hay alguna manera de hacer que el shell cmd de Windows expanda las rutas comodín?

37

Ocasionalmente, la incapacidad del cmd shell para expandir las rutas comodín puede ser realmente un inconveniente. Tuve que pasar 100 archivos en un directorio a un programa, y ​​no pude escribir * .ext. En cambio, utilicé 'ls' de mingw para volcar la lista en un archivo, luego reemplacé las nuevas líneas con espacios, las copié y pegué en cmd. Toda una pesadilla.

Sospecho que la respuesta será no, pero ¿alguien se ha ocupado de esto o ha encontrado alguna forma de facilitarlo?

cemulate
fuente
2
¿Has considerado usar algo como Powershell en su lugar?
I suspect the answer will be no, but has anyone dealt with this or come up with any way to make this easier? En realidad, estoy teniendo el problema opuesto, estoy tratando de encontrar una manera de hacer que el intérprete de comandos trate su lista como cadenas y evite que las convierta en comodines. Por ejemplo, for %i in (foobar baz really?) do @echo %itratará el último elemento ( really?) como un comodín nombre de archivo y saltar si no existen archivos con el nombre really1, reallyzetc. ☹
Synetech
1
@Synetech: ?no es un carácter legal para los nombres de archivo en el sistema de archivos de Windows. El personaje solo puede interpretarse como un comodín. Consulte Nombrar archivos, rutas y espacios de nombres en MSDN y Usar caracteres comodín en TechNet.
jww

Respuestas:

18

DOS, y en consecuencia Windows ' cmd.exe, nunca admitieron la expansión de comodines por parte del shell. Siempre dependía de la aplicación hacer la expansión.

Esto significa que siempre tendrá que encontrar otra ruta si está utilizando una aplicación que no admite la expansión. Tú podrías:

  • Use un bucle FOR para ejecutar algunos comandos contra todos los archivos que le interesan
  • Use dir /b > list.txtpara usar el dircomando para realizar la expansión y coloque la lista de archivos en un archivo de texto (luego puede usar algo como una fórmula de Excel si realmente está desesperado por producir una lista de comandos para pegar cmd, o puede usar Excel para transponer las celdas de modo que todos los nombres de archivo estén en la misma línea).
Malvinoso
fuente
Explicó que sería una pesadilla generar resultados de dir en un archivo y procesar el filtrado y la copia manualmente. La respuesta de wmz y, por supuesto, la mía funcionaría sin filtrar manualmente el contenido de un archivo.
wullxz
1
@wullxz: Tal vez, pero para alguien que no esté familiarizado con Powershell que quiera hacer esto de forma puntual, podría ser considerablemente más rápido, y la idea detrás de este sitio es proporcionar soluciones útiles para que las personas de todos los niveles de habilidades se refieran de vez en cuando el futuro, así que realmente no hay necesidad de regañarme porque crees que mi respuesta no es tan buena como la tuya.
Malvineous
1
"DOS y, en consecuencia, cmd.exe de Windows, nunca admitieron la expansión de comodines por parte del shell". - No es cierto según Microsoft. Consulte Uso de caracteres comodín en TechNet. (Pero creo que tiene razón en la práctica: o. De lo contrario, no estaría aquí tratando de averiguar por qué los archivos no coinciden)
jww
1
@jww: el enlace que publicaste explica el uso estándar de los caracteres comodín, pero no veo ninguna mención de que el shell los haya expandido. A diferencia de UNIX (y más tarde Linux y Mac), Microsoft dejó la expansión de comodines a cada aplicación individual para implementar, pasando los parámetros de la línea de comandos tal cual.
Malvineous
1
El comando DOS 'dir Filespec / b' funciona muy bien, porque crea una lista de archivos, uno por línea. Con el modificador '/ s' adicional, los nombres de los archivos están totalmente calificados (absolutos) y se pueden alimentar fácilmente a través de un bucle for a cualquier otro programa de línea de comandos que tome un nombre de archivo. Es lo mejor que podemos hacer, ya que Windows no tiene una función de bloqueo adecuada.
David A. Gray
9

Simplemente use Powershell, que está preinstalado en Windows 7. Powershell es capaz de ejecutar comandos cmd y entiende los comodines en cualquier lugar de una ruta.

Para iniciar Powershell, simplemente escriba "powershell" en el cuadro de búsqueda del menú de inicio y presione Intro.


En caso de que la aplicación espere una cadena con todos los nombres de archivo, esta es la secuencia de comandos correcta:

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

Cambie $delimiter = " "a $delimiter = ","si su aplicación espera una lista de nombres de archivos separados por comas.

Explicación del código:

  • [string]$files = $nothing - crea una variable de tipo vacía string
  • ; - ¡es un separador para múltiples comandos, no una tubería!
  • ls *.txt | % { $files += $_.fullname + $delimiter } - obtiene una lista de todos los archivos de texto y crea una cadena con todos los nombres de archivo separados por el delimitador
  • application.exe $files - llama a la aplicación y le pasa la lista de archivos

Incluso puede buscar un patrón de archivo de forma recursiva agregando -recursepara ls *.txtque el código completo se vea así:

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

Editar:
para evitar irritaciones, lsy dirson alias de Get-ChildItemy %es un alias para ForEach-Object. Mantengo mi código con alias usados ​​porque es más corto.

EDITAR 25/04/2018:
en 2012 he sido bastante nuevo en PowerShell. Por supuesto, hay una manera más fácil, aunque no es tan fácil como la capacidad de expansión global de Unix / Linux:

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

Explicación:

  • $ () evaluará primero la expresión dentro y se reemplazará con el resultado de esa expresión (al igual que los backticks hacen en bash)
  • ls *.txt obtiene objetos FileInfo de todos los archivos que coinciden con el glob *.txt
  • debido a que PowerShell está orientado a objetos, tenemos que generar el nombre completo de cada objeto FileInfo. Simplemente nombrar un atributo / propiedad en PowerShell lo genera de manera predeterminada. % { $_.FileName }hace eso por nosotros %recorre todos los elementos devueltos por lscada nombre de archivo de los objetos.
wullxz
fuente
2
Aunque PS es ciertamente capaz de cumplir con los requisitos y el consejo para familiarizarse con él es sólido, no es tan simple como sugiere. Correr start notepad++ *.txt(con intención de abrir todos los archivos de texto - el bloc de notas usado ++, ya que hace manejar varios nombres) se llevará a ninguna parte
wmz
1
Podrías solucionar eso con dir *.txt | % { notepad++.exe $_ }. Lo intenté con el bloc de notas simple, porque no tengo notepad ++, y funcionó. El comando recibe una lista de todos los archivos txt en el directorio actual, pasa la lista al siguiente comando que recorre la lista y ejecuta notepad ++ con el nombre de archivo como parámetro.
wullxz
Sí, pero esto no es equivalente. Piense grep "a b c"en encontrar cualquiera de las cadenas enumeradas, donde "ab c" se expandiría en la lista
wmz
55
Ejecutar un comando con una lista de elementos como parámetro no es equivalente a ejecutar un comando varias veces con cada elemento de una lista como parámetro. Otro ejemplo: copy a+b+c resulty copy a result copy b result copy c result. (y grep como utilidad existe en PS, se llama select-string)
wmz
1
votado, por cierto, es una lástima que OP no quiera intervenir para explicar ...
wmz
8

Esto le dará una lista y también la colocará en una variable llamada expanded_list. Póngalo en un archivo por lotes y ejecute con myBatchFile name myPattern. Encierre el patrón con comillas si incluye espacios. Coincide con archivos, sin directorios. Ejecutar sin parámetros coincide con 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%

Luego puede ejecutar su comando con my_command_exec %expanded_list%

¡ADVERTENCIA! El tamaño máximo de la variable cmd es de 8191 caracteres (XP en adelante), por lo que es posible desbordarlo. No puede contar con la utilidad que siempre le dará una lista completa. Por otro lado, la longitud máxima de la línea cmd también es 8191, por lo que no podrá ejecutarla de todos modos.

wmz
fuente
Tenga en cuenta que si no se especifican argumentos, expand_list se establecerá en todos los archivos en el directorio actual que puede o no ser lo que se desea, por lo que es posible que desee agregar verificación para ningún argumento (por ejemplo, si "% 1" == "" ...)
JasonM1
3

Esto funciona en cmd.exe

dir /b *.ext

o

echo | dir /b *.ext
usuario619818
fuente
Esto solo funciona para el nombre del archivo, no para ninguna parte de la ruta. Por ejemplo dir /b TortoiseSVN\bin\sv*.exemostrará svn.exey svnadmin.exe. Pero dir /b TortoiseSVN\bi*\svn.exemuestra un error de sintaxis.
styfle
1
comprobar dir /s /b. Esto te da el camino completo.
WesternGun
3

Tenga en cuenta que esto está en Comentario a los carteles en un hilo separado user619818 y styfle)

DIR puede y permite buscar en todos los subdirectorios archivos que coincidan con un tipo específico.

Nota: Se asume que el directorio raíz para verificar en qué se encuentran todos los subdirectorios es "C: \ Mi programa \ Root \" ya que el autor no proporcionó un nombre de ruta bajo el cual se encuentran estos directorios

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

esto le dará las rutas completas de los archivos y los nombres de los archivos fuente.

si solo desea nombres de archivos, tendría que hacer lo siguiente

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

así que suponiendo que desea mover todos estos archivos de "C: \ Mi programa \ Root \ Sub Directorios \ *. ext" a "D: \ Singlefolder \ *. ext" simplemente haga esto:

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

Espero que ayude a otros en el futuro. :)

Ben Personick
fuente
1

Esto es antiguo, pero con el subsistema Linux para Windows, es bastante común tener bash en tu RUTA ahora. Si ese es el caso, entonces este podría ser el truco para usted:

bash -c 'cat *.txt'
Ricardo
fuente
tenga en cuenta que las comillas simples no son especiales en cmd de Windows , por lo tanto, si ejecuta el comando anterior desde cmd, no funcionará. Y esto también se aplica a sistemas con Cygwin u otros entornos bash
phuclv