Cómo hacer un bucle a través de archivos que coincidan con comodín en un archivo por lotes


Tengo un conjunto de nombres de archivo base, para cada nombre 'f' hay exactamente dos archivos, 'f.in' y 'f. fuera'. Quiero escribir un archivo por lotes (en Windows XP) que pase por todos los nombres de archivo, para cada uno debería:

  • Mostrar el nombre base'f'
  • Realizar una acción en 'f.in"
  • Realizar otra acción en 'f.out'

No tengo ninguna manera de listar el conjunto de nombres de archivo base, aparte de buscar *.in (o *.out) por ejemplo.

Author: George Stocker, 2008-09-02

7 answers

Suponiendo que tiene dos programas que procesan los dos archivos, process_in.exe y process_out.exe:

for %%f in (*.in) do (
    echo %%~nf
    process_in "%%~nf.in"
    process_out "%%~nf.out"
)

%%~nf es un modificador de sustitución, que expande %f a un nombre de archivo solamente. Ver otros modificadores en https://technet.microsoft.com/en-us/library/bb490909.aspx (a mitad de la página) o simplemente en la siguiente respuesta.

 252
Author: Jim Buck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-16 08:17:15

Puede usar esta línea para imprimir el contenido de su escritorio:

FOR %%I in (C:\windows\desktop\*.*) DO echo %%I 

Una vez que tenga la variable %%I es fácil realizar un comando en ella (simplemente reemplace la palabra echo con su programa)

Además, se ha mejorado la sustitución de referencias de variables por Ahora puede usar la siguiente sintaxis opcional:

%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only (directory with \)
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file
%~$PATH:I   - searches the directories listed in the PATH
               environment variable and expands %I to the
               fully qualified name of the first one found.
               If the environment variable name is not
               defined or the file is not found by the
               search, then this modifier expands to the
               empty string


[https://ss64.com/nt/syntax-args.html][1]

En los ejemplos anteriores %I y PATH se pueden reemplazar por otros válidos valor. La sintaxis %~ se termina con un nombre de variable válido para. Picking nombres de variables en mayúsculas como %I lo hace más legible y evita la confusión con los modificadores, que no distinguen entre mayúsculas y minúsculas.

Puede obtener la documentación completa escribiendo FOR /?

 76
Author: Mark Ingram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-21 04:32:03

La forma más fácil, como yo lo veo, es usar un bucle for que llama a un segundo archivo por lotes para el procesamiento, pasando a ese segundo archivo el nombre base.

Según el for /? ayuda, basename se puede extraer usando la opción nifty ~n. Por lo tanto, el script base sería:

for %%f in (*.in) do call process.cmd %%~nf

Entonces, en proceso.cmd, suponga que %0 contiene el nombre base y actúe en consecuencia. Por ejemplo:

echo The file is %0
copy %0.in %0.out
ren %0.out monkeys_are_cool.txt

Podría haber una mejor manera de hacer esto en un script, pero siempre he estado un poco confuso sobre cómo tirar de múltiples comandos en un solo bucle for en un archivo por lotes.

EDITAR: ¡Eso es fantástico! De alguna manera había perdido la página en los documentos que mostraban que se podían hacer bloques de varias líneas en un bucle FOR. Voy a tener que volver atrás y reescribir algunos archivos por lotes ahora...

 5
Author: Nathan Fritz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-03 01:51:51

Hay una herramienta que normalmente se usa en Servidores MS (por lo que puedo recordar) llamada forfiles :

El enlace anterior contiene ayuda, así como un enlace a la página de descarga de Microsoft.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-02 14:23:40

Expandiendo el mensaje de Nathans. Lo siguiente hará el lote de trabajo en un archivo por lotes.

@echo off

if %1.==Sub. goto %2

for %%f in (*.in) do call %0 Sub action %%~nf
goto end

:action
echo The file is %3
copy %3.in %3.out
ren %3.out monkeys_are_cool.txt

:end
 3
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:01

El siguiente código filtra los nombres de los archivos que comienzan con la subcadena dada. Podría cambiarse para adaptarse a diferentes necesidades trabajando en la extracción subfname substring y la instrucción IF:

echo off
rem filter all files not starting with the prefix 'dat'
setlocal enabledelayedexpansion
FOR /R your-folder-fullpath %%F IN (*.*) DO (
set fname=%%~nF
set subfname=!fname:~0,3!
IF NOT "!subfname!" == "dat" echo "%%F"
)
pause
 0
Author: Sandro Rosa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-23 08:57:50

Haciéndose eco f.in y f. out separará el concepto de qué bucle y qué no bucle cuando se usa en un bucle for /f.

::Get the files seperated
echo f.in>files_to_pass_through.txt
echo f.out>>files_to_pass_through.txt

for /F %%a in (files_to_pass_through.txt) do (
for /R %%b in (*.*) do (
if "%%a" NEQ "%%b" (
echo %%b>>dont_pass_through_these.txt
)
)
)
::I'm assuming the base name is the whole string "f".
::If I'm right then all the files begin with "f".
::So all you have to do is display "f". right?
::But that would be too easy.
::Let's do this the right way.
for /f %%C in (dont_pass_through_these.txt)
::displays the filename and not the extention
echo %~nC
)

Aunque no preguntaste, una buena manera de pasar comandos en f.in y f. fuera sería a...

for /F %%D "tokens=*" in (dont_pass_through_these.txt) do (
for /F %%E in (%%D) do (
start /wait %%E
)
)

Un enlace a todos los comandos de Windows XP:link

Me disculpo si no respondí esto correctamente. La pregunta fue muy difícil de leer para mí.

 0
Author: Z. Mickaels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-16 02:16:36