Alterar temporariamente o diretório para o comando de arquivo em lote único

19

Em scripts de shell, se eu precisar executar um comando a partir de um diretório, podemos usar um subshell para garantir que eu retorne ao contexto original:

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

Isso pode ser feito em arquivos em lotes do Windows (ou arquivos cmd)

Fazer o mesmo em arquivos em lote me deixa no novo diretório.

Eu posso fazer:

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

Mas o popd depende do sucesso de command.

Alguma ideia?

Greg
fonte
Como você está chamando seu "arquivo em lote" ou "arquivo cmd"? Se você colocar um comando cd em um script de shell e executar esse script (não for originado), o diretório de trabalho atual do shell de chamada não será alterado.
22811 garyjohn
Só para ficar claro, isso se refere aos arquivos em lotes do Windows.
Greg
É um script que executa vários comandos em diferentes partes de uma árvore de diretórios. Alguns dos comandos operam apenas no diretório atual. Retornar ao diretório original ajuda a simplificar os dados que controlam o script. Você está sugerindo criar um arquivo em lotes separado para cada diretório em que eu preciso fazer chamadas?
Greg
Pelo que me lembro, você se referiu a scripts de shell e não mencionou o Windows na sua pergunta original, então assumi incorretamente que você estava usando um sistema semelhante ao Unix. Agora eu entendo.
3051111
Sim, desculpe, eu percebo que não era clara (embora eu acho que 'batch-file' era um :-P dica)
Greg

Respostas:

21

Se você fizer:

pushd \windows && foobar && popd

você será deixado (como você declara) na pasta \ windows. Experimentar:

pushd \windows & foobar & popd

e você deve voltar aonde começou.

BillP3rd
fonte
11
Ah, um único e comercial é o equivalente a ponto e vírgula em sh. Perfeito. (e uma referência: ss64.com/nt/syntax-conditional.html )
Greg
6
É bom lembrar que cd/ pushdàs vezes falha (se o diretório não existir, por exemplo). pushd \windows && (foobar & popd)pode ser mais confiável
grawity
16

Por padrão, os arquivos em lotes do Windows são executados no contexto do shell pai (o que é incomum para usuários do Unix, onde sourceé necessário um explícito , mas era a única possibilidade no MS-DOS). Isso significa que mudanças de diretório e variáveis ​​de ambiente também afetam o shell interativo original.

Coloque setlocalna parte superior do seu script para executá-lo em seu próprio contexto - você pode usá-lo com segurança cddentro do script.

gravidade
fonte
Obrigado, isso parece o que eu preciso - vou verificá-lo quando tiver acesso a uma máquina Windows. Isso afetaria os subcomandos usando parênteses?
Greg
11
@ Greg: Parece que ( )apenas agrupa comandos juntos, mas ainda os executa no contexto pai. (setlocal & cd foo & bar)não funciona; em vez disso pushd foo && (bar & popd)seria necessário.
grawity
4

Como o grawity mencionado anteriormente, pushd \windows && (foobar & popd)funcionaria melhor do que pushd \windows & foobar & popdporque o último pode falhar se não houver esse diretório.

Além disso, usar setlocale endlocalpermitir que você tenha vários ambientes locais; por exemplo, você pode ter:

setlocal

cd dir

command

endlocal

Agora você estaria de volta ao seu diretório original.

Timtech
fonte
3

Você pode usar cd -para voltar ao diretório de trabalho anterior. E use em ;vez de &&, então os comandos subseqüentes não dependerão do sucesso dos comandos anteriores.

$ pwd
/etc
$ cd /var ; pwd ; cd -
/var
$ pwd
/etc
bahamat
fonte
Atualizei a pergunta para esclarecer que estou perguntando sobre o script de lote / shell do Windows. Eu sei como fazê-lo em um shell sh-like :)
Greg
Como BillP3rd apontou o equivalente a ';' em arquivos em lote é '&'.
Greg
Ah desculpa. Seu uso de barras me fez pensar que era o UNIX.
bahamat 30/07/11
1

Aplaudo a sugestão de grawity de colocar setlocalno início do script em lote, mas acrescentaria o fato de que você pode ter vários blocos aninhados setlocal/ endlocal, para que uma resposta mais relevante à pergunta possa ser

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

E, é claro, se você deseja que o comando seja executado apenas se o cdto dir2for bem-sucedido, digamos .cddir2&&command

Observe que o bloco setlocal/ endlocalcria um ambiente localizado; portanto, qualquer variável que você definir ou alterar nesse bloco voltará ao seu valor anterior após o endlocal.

Scott
fonte
0

Você pode salvar o diretório atual em uma variável. Mude e mude de volta, dependendo do valor de retorno do comando. BTW,% CD% retorna seu DIR atual.

surfasb
fonte