2009-06-24 40 views
15

Estoy trabajando en un script por lotes que me permitirá eliminar archivos más antiguos que un período establecido usando forfiles. Por ahora, mi objetivo es imprimir los archivos que se eliminarán.Forfiles Batch Script (Escaping @ character)

La invocación forfiles que estoy usando funciona sin problemas desde un shell cmd.exe, pero tan pronto como lo incrusto en un script por lotes, se convierte en barfs. Sospecho que esto se debe a que el carácter @ no se ha escapado correctamente, pero no estoy seguro.

El comando que estoy corriendo es:

forfiles /S /P "r:\" /m *.bak /d -10 /c "cmd /c echo @PATH" 

Y el resultado es el siguiente error:

ERROR: Invalid argument/option - '@PATH' 
Type "FORFILES /?" for usage. 

He buscado en Google por todo el lugar y trató algunos esquemas diferentes para escapar el componente @PATH. Todo desde @@ RUTA, a \ "@ PATH \" sin resultados.

¡Cualquier ayuda sería apreciada!

EDIT: También debe tener en cuenta que estoy basando gran parte de mi conocimiento de forfiles de here.

Respuesta

33

tuve el mismo problema hasta que me quita las comillas alrededor de la ruta del directorio, así:

forfiles /S /P r:\ /m *.bak /d -10 /c "cmd /c echo @PATH" 

Espero que ayude.

+0

Extracción de las cotizaciones trabajado! ¡Muchas gracias! Me parece increíblemente extraño que poner comillas alrededor de una ruta de archivo (un procedimiento estándar) rompa un argumento separado al comando de una manera tan obvia. – Paradox

+0

Sí, es bastante extraño, pero he tenido el mismo problema en este momento. Buena solución. :) – jsight

+1

Gracias, pero esto es estúpido. ¿Por qué, en 2012, tuve que convertir mi ruta a un formato DOS 'f: \ MySQLB ~ 1 \'? LOL. ¡Pero al menos funciona ahora! – cbmeeks

0

Ponga forfiles.exe para que funcione correctamente, de lo contrario no pasará el @variables cuando utiliza un archivo por lotes. Forfiles funcionará si se encuentra en el símbolo del sistema, pero cuando lo ejecuta en un archivo de proceso por lotes las variables no funcionan bien a menos que escriba: forfiles.exe.

Aquí es un ejemplo de que borra algunos archivos txt más de 30 días forfiles.exe /P c:\directory\ /M *.txt /C "cmd /c del @path" /d -30

17

Intenta recortar el \ detrás de su camino /P. Entonces debería poder usar comillas para encapsular una ruta que incluya un espacio.

+2

esto funcionó para mí. Gracias :) – KK99

+2

¡Yo también! no te pierdas esto –

+1

esto también funciona y es probablemente un mejor enfoque ya que te permitirá manejar nombres con espacios –

0

Encontré que hay dos versiones de FORFILES, una es la versión 1998 (gracias a Emmanuel Boersma), y la otra es la versión 2005 (la fecha de modificación lo muestra).

FORFILES v 1.1 - by Emmanuel Boersma - 4/98 

Syntax : FORFILES [-pPath] [-mSearch Mask] [-ccommand] [-dDDMMYY] [-s] 

-pPath    Path where to start searching 
-mSearch Mask  Search files according to <Search Mask> 
-cCommand   Command to execute on each file(s) 
-d[+|-][DDMMYY|DD] Select files with date >= or <=DDMMYY (UTC) 
        or files having date >= or <= (current date - DD days) 
-s     Recurse directories 
-v     Verbose mode 

The following variables can be used in Command : 
@FILE, @PATH, @RELPATH, @ISDIR, @FSIZE, @FDATE, @FTIME 

Default : <Directory : .> <Search Mask : *.*> <Command : "CMD /C Echo @FILE"> 
Examples : 
FORFILES -pc:\ -s -m*.BAT -c"CMD /C Echo @FILE is a batch file" 
FORFILES -pc:\ -s -m*.* -c"CMD /C if @ISDIR==TRUE echo @FILE is a directory" 
FORFILES -pc:\ -s -m*.* -d-100 -c"CMD /C Echo @FILE : date >= 100 days" 
FORFILES -pc:\ -s -m*.* -d-010193 -c"CMD /C Echo @FILE is quite old!" 

Cada versión tiene su sintaxis única.

FORFILES [/P pathname] [/M searchmask] [/S] 
     [/C command] [/D [+ | -] {MM/dd/yyyy | dd}] 

Description: 
    Selects a file (or set of files) and executes a 
    command on that file. This is helpful for batch jobs. 

Parameter List: 
    /P pathname  Indicates the path to start searching. 
         The default folder is the current working 
         directory (.). 

    /M searchmask Searches files according to a searchmask. 
         The default searchmask is '*' . 

    /S     Instructs forfiles to recurse into 
         subdirectories. Like "DIR /S". 

    /C command  Indicates the command to execute for each file. 
         Command strings should be wrapped in double 
         quotes. 

         The default command is "cmd /c echo @file". 

         The following variables can be used in the 
         command string: 
         @file - returns the name of the file. 
         @fname - returns the file name without 
            extension. 
         @ext  - returns only the extension of the 
            file. 
         @path - returns the full path of the file. 
         @relpath - returns the relative path of the 
            file. 
         @isdir - returns "TRUE" if a file type is 
            a directory, and "FALSE" for files. 
         @fsize - returns the size of the file in 
            bytes. 
         @fdate - returns the last modified date of the 
            file. 
         @ftime - returns the last modified time of the 
            file. 

         To include special characters in the command 
         line, use the hexadecimal code for the character 
         in 0xHH format (ex. 0x09 for tab). Internal 
         CMD.exe commands should be preceded with 
         "cmd /c". 

    /D date   Selects files with a last modified date greater 
         than or equal to (+), or less than or equal to 
         (-), the specified date using the 
         "MM/dd/yyyy" format; or selects files with a 
         last modified date greater than or equal to (+) 
         the current date plus "dd" days, or less than or 
         equal to (-) the current date minus "dd" days. A 
         valid "dd" number of days can be any number in 
         the range of 0 - 32768. 
         "+" is taken as default sign if not specified. 

    /?     Displays this help message. 

Examples: 
    FORFILES /? 
    FORFILES 
    FORFILES /P C:\WINDOWS /S /M DNS*.* 
    FORFILES /S /M *.txt /C "cmd /c type @file | more" 
    FORFILES /P C:\ /S /M *.bat 
    FORFILES /D -30 /M *.exe 
      /C "cmd /c echo @path 0x09 was changed 30 days ago" 
    FORFILES /D 01/01/2001 
      /C "cmd /c echo @fname is new since Jan 1st 2001" 
    FORFILES /D +3/19/2012 /C "cmd /c echo @fname is new today" 
    FORFILES /M *.exe /D +1 
    FORFILES /S /M *.doc /C "cmd /c echo @fsize" 
    FORFILES /M *.txt /C "cmd /c if @isdir==FALSE notepad.exe @file" 

Diviértete haciendo que "Batch File" sea más sofisticado. :)

2

Esta es una pregunta anterior, pero tengo una respuesta diferente ... en caso de que alguien lo necesite.

Al utilizar 'forfiles', la ruta (escrita después de/p) PUEDE estar entre comillas. Sin embargo, no debe terminar con una barra inclinada.

Si desea ejecutar 'forfiles' para el directorio raíz de una unidad:
forfiles /p "C:" /c "cmd /c echo @file"

Si desea procesar los archivos en un directorio diferente ...
forfiles /p "C:\Program Files" /c "cmd /c echo @file"

En otras palabras , el enfoque más seguro es:

  • Siempre use comillas (porque las carpetas con espacios, como 'Archivos de programa', seguirán funcionando)
  • siempre omiten la última barra final

forfiles /p "C:\Path\Without\Trailing\Slash"

+0

Acabo de darme cuenta de que Abdul Rahman y lolquotes han resumido bastante mi respuesta ... en diciembre de 2011. ¡Bien! – hbCyber

+0

Esta respuesta no funciona. Al especificar una letra de unidad y dos puntos (por ejemplo, "D:") para la ruta, forzará que FORFILES busque en el directorio actual de esa unidad (cada unidad mantiene su propio "directorio actual"). – andyb

+0

Siempre omita la última barra final: ese fue el factor decisivo para mí – twoleggedhorse

0
dir *.* > C:\path\dummy%date:~4,2%%date:~7,2%%date:~10,4%.DAT 

dir *.* > C:\path\dummy%date:~4,2%%date:~7,2%%date:~10,4%.csv 

forfiles -p C:\path\ -m *.DAT /d -50 /c "cmd /c del /Q @path" 
forfiles -p C:\path\ -m *.csv /d -50 /c "cmd /c del /Q @path" 
  1. Reemplazar el .dat y archivos .csv u lo que desea eliminar.

  2. -50 borrar mayor de 50 días

  3. Este es el archivo por lotes ventanas

0

no funcionaba

FORFILES /P %deletepath% /M *.%extension% /D -%days% /C "cmd /c del @PATH"

funcionaba

FORFILES /P %deletepath% /M *.%extension% /D -%days% /C "cmd /c del @path"

@path in lower case works.

Después de buscar en todas partes encontré la respuesta en mis propias pruebas. Utilizando la última versión en el servidor 2012 R2 intenté cambiar @PATH a minúsculas. Esto me lo arregló.

¡Buena suerte!

0

La mejor práctica sería usar comillas dobles alrededor del parámetro path (/ P) para manejar las rutas con espacios.

El problema ocurre cuando el varialble de sustitución contiene una barra diagonal inversa. La barra invertida 'escapa' de la cita, haciendo que FORFILES malinterprete el resto de la línea de comando.

Por convención, la ruta a un directorio no necesita la barra diagonal inversa, con la única excepción de que es el directorio raíz. Especificar solo la letra de la unidad y dos puntos C: NO se refiere a la raíz, sino que se refiere al "directorio actual" para esa unidad. Para referirse a la raíz, uno debe usar la barra invertida trasera C:\.

Mi solución es como sigue:

Al utilizar forfiles, añadir una . antes del cierre "del parámetro /P por ejemplo

FORFILES /P "%somePath%." /C "CMD /C ECHO @path" 

Después de la sustitución, esto conduce a caminos de la forma C:\., C:\TEMP. o C:\TEMP\.. Todos estos son tratados correctamente por FORFILES y también DIR.

no he probado todas las posibles variables de sustitución forfiles, ser @path parece ser afectado por la adición de la .