Obtener el directorio actual de archivos por lotes

283

En primer lugar, vi este tema pero no pude entenderlo.

Pregunta:

Hay un archivo por lotes D:\path\to\file.batcon el siguiente contenido:

echo %cd%
pause

Salida es:

C:\

Debe ser D:\path\to

¿Qué estoy haciendo mal?

Hamed Kamrava
fuente
77
Debería leer todas las respuestas a una pregunta, especialmente los que obtienen más votos, no solo la aceptada. La respuesta con la puntuación más alta en su enlace publicado ya responde a su pregunta.
dbenham
44
Si está en c: \ cuando escribe el nombre del archivo por lotes, entonces c: \ es lo que imprimirá% cd%.
foxidrive

Respuestas:

496

La variable de solo lectura del sistema %CD%mantiene la ruta del llamante del lote, no la ubicación del archivo del lote.

Puede obtener el nombre de la secuencia de comandos por lotes, tal como la escribió el usuario con %0(p scripts\mybatch.bat. Ej .). Las extensiones de parámetros se pueden aplicar a esto, por %~dp0lo que devolverá la unidad y la ruta al script por lotes (por ejemplo W:\scripts\) y %~f0devolverá el nombre de ruta completo (por ejemplo W:\scripts\mybatch.cmd).

Puede hacer referencia a otros archivos en la misma carpeta que el script por lotes utilizando esta sintaxis:

CALL %0\..\SecondBatch.cmd

Esto incluso se puede usar en una subrutina, Echo %0le dará la etiqueta de la llamada pero echo "%~nx0"le dará el nombre del archivo del script por lotes.

Cuando el %0 variable se expande, el resultado se encierra entre comillas.

Más sobre los parámetros del lote .

Stoleg
fuente
1
Mira, no necesito correr stm.sqladentro D:\Dir1\Dir2\stm.sql. Necesito mysql.exe -u root -p mysql < %cd%\stm.sqlejecutar esos comandos stm.sql.
Hamed Kamrava
@HamedKamrava, ¿es para mi lote SQL? ¿No es un archivo por lotes como *.bato *.sh?
Stoleg
@ Stoleg- De hecho, hay 2 archivos en D:\Dir1\Dir2\batchfile.baty D:\Dir1\Dir2\stm.sql. el contenido de batchfile.bat es: mysql.exe -u root -p mysql < D:\Dir1\Dir2\stm.sqly el contenido de stm.sql es algunos comandos de MySQL.
Hamed Kamrava
1
La variable de solo lectura del sistema% CD% mantiene la ruta del llamante del lote, no la ubicación del archivo del lote.
Stoleg
34
echo %~dp0devolverá la ruta a la ubicación del lote. echo %~f0devolverá la ruta al lote con el nombre del archivo.
Stoleg
119

Muy simple:

setlocal
cd /d %~dp0
File.exe
shay
fuente
9
El código es corto pero no es fácil de entender. ¿Qué es este File.exe? ¿La ruta actual del directorio está almacenada en% ~ dp0?
Ivailo Bardarov
Esta respuesta en realidad responde a la pregunta, creo. Prestigio.
macetw
3
Acabo de usar cd /d %~dp0como primera línea de archivo por lotes y trabajé
mkb
¿Por qué necesita setlocal? vuelve bien sin eso también?
T.Todua
1
@ T.Todua "setlocal" hace que cualquier cambio en el entorno, incluido el directorio actual, esté contenido hasta que finalice el archivo por lotes o se encuentre un "endlocal". Si va a cambiar las variables de entorno o el directorio actual, es una buena forma.
Jamie
30

Dentro de su archivo .bat:

set mypath=%cd%

Ahora puede usar la variable %mypath%para hacer referencia a la ruta del .batarchivo al archivo. Para verificar que la ruta es correcta:

@echo %mypath%

Por ejemplo, un archivo llamado DIR.batcon los siguientes contenidos

set mypath=%cd%
@echo %mypath%
Pause

ejecutar desde el directorio g:\test\bathará eco de esa ruta en la ventana de comandos de DOS.

rockerron
fuente
1
esta es la mejor y más simple solución
Nani
77
Esta no es una buena solución porque no tiene en cuenta el script por lotes que se llama desde otro archivo en otra ruta.
theQuestionMan
también cuando se ejecuta como permisos elevados, el% cd% devuelve C: \ Windows \ system32 pero no el directorio donde está almacenado.
PravyNandas
9

Esto es lo que uso en la parte superior de todos mis archivos por lotes. Acabo de copiar / pegar desde mi carpeta de plantillas.

@echo off
:: --HAS ENDING BACKSLASH
set batdir=%~dp0
:: --MISSING ENDING BACKSLASH
:: set batdir=%CD%
pushd "%batdir%"

Establecer la ruta del archivo por lotes actual en% batdir% le permite llamarlo en los siguientes pasos en el archivo por lotes actual, independientemente de dónde cambie este archivo por lotes. El uso de PUSHD le permite usar POPD para establecer rápidamente la ruta de este archivo por lotes al% batdir% original. Recuerde, si usa% batdir% ExtraDir o% batdir% \ ExtraDir (dependiendo de la versión utilizada anteriormente, finalizando la barra invertida o no) deberá encerrar la cadena completa entre comillas dobles si la ruta tiene espacios (es decir, "% batdir% ExtraDir" ) Siempre puede usar PUSHD% ~ dp0. [https: // ss64.com/ nt / syntax-args .html] tiene más información sobre (% ~) parámetros.

Tenga en cuenta que usar (: :) al comienzo de una línea la convierte en una línea de comentario. Más importante aún, el uso de :: le permite incluir redirectores, tuberías, caracteres especiales (es decir, <> | etc.) en ese comentario.

:: ORIG STMT WAS: dir *.* | find /v "1917" > outfile.txt

Por supuesto, Powershell hace esto y mucho más.

Wendell Holmes
fuente
2
Gran respuesta, muchas gracias! :-) Solo ten cuidado con tu segunda técnica ( set batdir=%CD%). No está bien, porque es la ruta a la persona que llama, no el archivo bat en sí. La única forma válida de obtener la ruta al archivo bat en ejecución es %~dp0.
Mitch McMabers