Cambiar temporalmente el directorio para un solo comando de archivo por lotes

19

En shell-scripting, si necesito ejecutar un comando desde un directorio, puedo usar una subshell para asegurarme de que regrese al contexto original:

(cd temporary/new/directory ; command)
# now I am still in original directory

¿Se puede hacer esto en archivos por lotes de Windows (o archivos cmd)

Hacer lo mismo en los archivos por lotes me deja en el nuevo directorio.

Puedo hacer:

pushd temporary\new\directory && command && popd

Pero el popd depende del éxito de command.

¿Algunas ideas?

Greg
fuente
¿Cómo invoca su "archivo por lotes" o "archivo cmd"? Si coloca un comando de CD en un script de shell y ejecuta ese script (no lo obtiene), el directorio de trabajo actual del shell de llamada no cambiará.
garyjohn
Para ser claros, esto se refiere a los archivos por lotes de Windows.
Greg
Es un script que ejecuta un montón de comandos en diferentes partes de un árbol de directorios. Algunos de los comandos solo operan en el directorio actual. Regresar al directorio original ayuda a simplificar los datos que impulsan el script. ¿Está sugiriendo hacer un archivo por lotes separado para cada directorio en el que necesito hacer llamadas?
Greg
Según recuerdo, se refirió a los scripts de shell y no mencionó Windows en su pregunta original, por lo que asumí incorrectamente que estaba utilizando un sistema similar a Unix. Ahora entiendo.
garyjohn
Sí, lo siento, me doy cuenta de que no estaba claro (aunque creo que 'batch-file' era una pista :-p)
Greg

Respuestas:

21

Si lo haces:

pushd \windows && foobar && popd

quedará (como usted dice) en la carpeta \ windows. Tratar:

pushd \windows & foobar & popd

y deberías volver a donde empezaste.

BillP3rd
fuente
1
Ah, entonces un ampersand es el equivalente de punto y coma en sh. Eso es perfecto. (y una referencia: ss64.com/nt/syntax-conditional.html )
Greg
66
Es bueno recordar que cd/ a pushdveces falla (si el directorio no existe, por ejemplo). pushd \windows && (foobar & popd)puede ser más confiable
user1686
16

Por defecto, los archivos por lotes de Windows se ejecutan en el contexto del shell principal (lo cual es inusual para los usuarios de Unix, donde sourcese necesita un explícito , pero era la única posibilidad en MS-DOS). Esto significa que los cambios de directorio y las variables de entorno también afectan al shell interactivo original.

Poner setlocalen la parte superior de su secuencia de comandos para que se ejecute en su propio contexto; puede usarla con seguridad cddentro de la secuencia de comandos.

usuario1686
fuente
Gracias. Esto suena como lo que necesito. Lo comprobaré cuando tenga acceso a una máquina con Windows. ¿Afectaría eso a los subcomandos usando paréntesis?
Greg
1
@Greg: Parece que ( )solo agrupa comandos, pero aún los ejecuta en el contexto principal. (setlocal & cd foo & bar)no trabajará; en cambio pushd foo && (bar & popd)sería necesario.
user1686
4

Como se mencionó anteriormente, pushd \windows && (foobar & popd)funcionaría mejor que pushd \windows & foobar & popdporque este último puede fallar si no existe dicho directorio.

Además, usar setlocaly le endlocalpermite tener múltiples entornos locales, por ejemplo, podría tener:

setlocal

cd dir

command

endlocal

Ahora estaría de vuelta en su directorio original.

Timtech
fuente
3

Puede usar cd -para volver al directorio de trabajo anterior. Y use en ;lugar de &&, luego los comandos posteriores no dependerán del éxito de los comandos anteriores.

$ pwd
/etc
$ cd /var ; pwd ; cd -
/var
$ pwd
/etc
bahamat
fuente
He actualizado la pregunta para aclarar que estoy preguntando sobre las secuencias de comandos de lote / shell de Windows. Yo sé cómo hacerlo bajo un sh-como :)
Greg
Como BillP3rd señaló el equivalente de ';' en archivos por lotes es '&'.
Greg
Oh, lo siento. Su uso de barras diagonales me hizo pensar que era UNIX.
bahamat
1

Aplaudo la sugerencia de Grawity de poner setlocalal comienzo de su secuencia de comandos por lotes, pero agregaría el hecho de que puede tener múltiples, anidados, setlocal/ endlocalbloques, por lo que una respuesta más relevante a la pregunta podría ser

@echo off
setlocal
cddir1
  ...
setlocal
cddir2
command
endlocal
:: Now I am back indir1
  ...

Y, por supuesto, si desea que el comando se ejecute solo si cdto to dir2tiene éxito, por ejemplo .cddir2&&command

Tenga en cuenta que el bloque setlocal/ endlocalcrea un entorno localizado, por lo que cualquier variable que establezca o cambie en dicho bloque volverá a su valor anterior después de endlocal.

Scott
fuente
0

Puede guardar el directorio actual en una variable. Cambiar y volver a cambiar según el valor de retorno del comando. Por cierto,% CD% devuelve su DIR actual.

surfasb
fuente