Questão Executar um comando de outro diretório no bash


Diga que estou fazendo isso:

cd subdir
git init
cd ../

Existe uma maneira de fazer isso com um único comando, ou talvez dois, em vez de ter que entrar e sair de um diretório para executar um comando lá?

(Não está procurando por uma solução específica de git; é apenas um exemplo).


87


origem




Respostas:


Esta é geralmente a melhor maneira:

( cd dir ; git init )

ou

( cd dir && git init )

É bem curto e fácil de digitar. Ele inicia um sub-shell, então você não pode modificar seu ambiente, mas isso não parece ser um problema aqui.


158



E se você precisar definir uma ou duas variáveis ​​de ambiente, basta adicionar isso como outro comando no início. - Hippo
@CraigMcQueen: não realmente. $? conterá o código de saída do último comando que foi executado no subshell. Se você usar o && variant (que você geralmente deveria), então você vai ter o código de saída do primeiro comando que falhou (ou 0 se tudo correu bem). - Mat
Eu acho que os parênteses são opcionais - Francis.Beauchamp
@ Francis.Beauchamp: se você omitir os parênteses, você estará no subdir após o comando, em vez de voltar para onde você começou. - Mat


Eu estava procurando uma maneira de executar o comando git de um caminho e fazer alterações no repositório em um caminho diferente. Então acabei nesta questão aqui.

Mas, para as minhas necessidades específicas, nem a resposta aceita nem nenhuma das outras ajudou.

Eu precisava executar comandos do git usando sudo -u USER /usr/bin/git (outro usuário executando). E como você deve saber, o sudo não me permite executar o cd comando, então eu não posso estar no diretório do repositório.

Então eu fui para página do man do git. E entre as opções, vi o --git-dir=<path>:

--git-dir =

Definir o caminho para o repositório. Isso também pode ser controlado definindo a variável de ambiente GIT_DIR. Pode ser um caminho absoluto ou um caminho relativo para o diretório de trabalho atual.

Então, se ajudar alguém, você ainda pode usar o git de um caminho e fazer mudanças em um repositório "longe de você". Apenas use:

git --git-dir=/path/to/repository GIT_COMMAND

ou, para executá-lo como outro usuário, faça algo como:

echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir=/path/to/repository GIT_COMMAND

Também de Página man do git-init:

Se a variável de ambiente $ GIT_DIR estiver configurada, ela especifica um caminho para usar em vez de ./.git para a base do repositório.

Então, se você quiser iniciar o repositório sob a pasta usual .git, você precisará especificá-lo junto com o --git-dir opção. por exemplo.:

echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir=/path/to/repository/.git init

Depois de inicializar o repositório em /path/to/repo/.git, todos os outros comandos devem ter a opção --work-tree=<path>, como descrito na página man do git:

--work-tree =

Definir o caminho para a árvore de trabalho. Pode ser um caminho absoluto ou um caminho relativo ao diretório de trabalho atual. Isso também pode ser controlado definindo a variável de ambiente GIT_WORK_TREE e a variável de configuração core.worktree (veja core.worktree em git-config (1) para uma discussão mais detalhada).

Então, o comando certo para executar o git como outro usuário e inicializar um novo repositório é:

echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir=/path/to/repository/.git init
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' add /path/to/repository/*
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' commit -m 'MESSAGE'
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' remote add origin user@domain.com:path
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' push -u origin master

20





Não é exatamente o que você está perguntando (você tem respostas reais acima com o subshell), mas veja pushd e popd


11



Eu tentei com cd && para maven e não funcionou, mas pushd e popd faz o trabalho perfeitamente. obrigado - Radu Toader


Você tem poucas opções. Você pode agrupar os comandos com && ou ;. Como isso:

cd subdir && git init && cd ..

ou

cd subdir; git init; cd ..

A diferença entre eles é que, no primeiro exemplo, se um dos comandos falhar, ele não executará o restante deles. No segundo exemplo, todos os comandos serão executados, não importa o quê.

Outra opção seria definir uma função e usá-la, por exemplo:

function cdinit() {
    cd $1
    git init
    cd ..
}

Então você pode executar o comando:

cdinit subdir

E isso vai automaticamente git init nesse diretório e sair dele.

Você também pode fazer uma solução mais complexa usando uma função se tiver vários diretórios e quiser git init eles com um comando.

function cdinit() {
    for arg in $@
    do
        cd $arg
        git init
        cd ..
    done
}

Você pode então executar isso com:

cdinit subdir1 subdir2 subdir3

E isso vai fazer git init dentro subdir1, subdir2e subdir3.


5



Obrigado. Eu estava ciente de && e ;, mas esperava por algo mais elegante. Parece que escrever um roteiro é minha melhor opção. - Trevor Burnham
Correção: Esta resposta está bem, mas a resposta de Mat é melhor para minhas necessidades particulares. - Trevor Burnham


No caso de git (pelo menos na versão 2.7.0), você pode aproveitar o -C opção que faz o git se comportar como se tivesse sido iniciado no diretório fornecido. Então, sua solução pode parecer:

> git -C subdir init
Initialized empty Git repository in /some/path/subdir/.git/

Citando a documentação:

Run as if git was started in <path> instead of the current working directory. When multiple -C options are given, each subsequent non-absolute -C
<path> is interpreted relative to the preceding -C <path>.

This option affects options that expect path name like --git-dir and --work-tree in that their interpretations of the path names would be made
relative to the working directory caused by the -C option. 

5





Você pode agrupar os comandos com &&, ou seja,

cd subdir && git init && cd ../

Se você não quer nenhuma dependência no código de saída de cada comando, você pode usar; em vez disso, ou seja:

cd subdir ; git init ; cd ../

2



Ou com ; para que eles não dependam do código de retorno do anterior. - slhck


Você tem que pular para o diretório de destino se o comando não tiver um nome de arquivo ou parâmetro de nome de diretório.

Mas você pode escrever um script bash que leva o diretório de destino e o comando como parâmetros. Para isso, você poderia dar uma olhada no pushd e popd: http://ss64.com/bash/pushd.html

Eu escreveria esse pequeno roteiro para você, mas eu não tenho uma caixa de Linux aqui :)


2



Acabei de ver a resposta de Mark Szymanski. Você pode simplesmente implementar um segundo parâmetro para um comando (e renomear o comando) e você tem o que deseja. - wullxz


Programas têm diferentes maneiras de lidar com argumentos, então alguns terão algum equivalente de -pasta = nome opção. Além dessa exceção, o padrão, mesmo no MS DOS, é simplesmente

$ programa subdirecionar

Às vezes você precisa

$ programa subdir /

O programa abrirá a pasta, trabalhará com ela da mesma maneira que você trabalha com um arquivo e, uma vez terminado, retornará o controle para o seu shell, que está apontado para o seu diretório padrão original. Programas manipulados desta forma tem o problema que saídas de erro (como core dumps) vão para um arquivo no diretório atual do seu shell (em vez de subdirecionar.)

Não há solução alternativa, a menos que o programa tenha opções de comando disponíveis para especificar um local diferente. Alguns programadores levam licença artística entre "o programa de diretório era chamado de"e" programa de diretório era disse para trabalhar em "


1