Временно изменить каталог для команды одного пакетного файла

Временно изменить каталог для команды одного пакетного файла

В скриптах оболочки, если мне нужно запустить команду из каталога, я могу использовать подоболочку, чтобы гарантировать возврат в исходный контекст:

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

Можно ли это сделать в пакетных файлах Windows (или cmd-файлах)?

Если сделать то же самое в пакетных файлах, то я окажусь в новом каталоге.

Я могу сделать:

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

Но popd зависит от успеха command.

Есть идеи?

решение1

Если вы это сделаете:

pushd \windows && foobar && popd

вы останетесь (как вы и указали) в папке \windows. Попробуйте:

pushd \windows & foobar & popd

и вы вернетесь туда, откуда начали.

решение2

По умолчанию пакетные файлы Windows запускаются в контексте родительской оболочки (что необычно для пользователей Unix, где sourceтребуется явное указание, но это была единственная возможность в MS-DOS). Это означает, что изменения каталогов и переменных окружения также влияют на исходную интерактивную оболочку.

Поместите setlocalв начало скрипта, чтобы он работал в своем собственном контексте — cdпосле этого вы можете безопасно использовать его внутри скрипта.

решение3

Как уже упоминалось ранее, Grawity pushd \windows && (foobar & popd)будет работать лучше, чем pushd \windows & foobar & popdпредыдущий, поскольку последний может дать сбой, если такого каталога не будет.

Кроме того, использование setlocalи endlocalпозволяет иметь несколько локальных сред, например:

setlocal

cd dir

command

endlocal

Теперь вы вернетесь в свой исходный каталог.

решение4

Я приветствую предложение Grawity разместить setlocalв начале вашего пакетного скрипта, но я бы добавил тот факт, что вы можете иметь несколько вложенных блоков setlocal/ endlocal, поэтому более уместным ответом на вопрос может быть

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

И, конечно, если вы хотите, чтобы команда выполнялась только в том случае, cdеслиdir2успешен, скажемcddir2&&command.

Обратите внимание, что блок setlocal/ endlocalсоздает локализованную среду, поэтому любые переменные, которые вы устанавливаете или изменяете в таком блоке, вернутся к своему предыдущему значению после endlocal.

Связанный контент