Passando um comando git como um argumento

2

Estou tentando automatizar algumas partes tediosas de um trabalho de estudante em que estou trabalhando.

Basicamente, o objetivo é clonar um monte de repositórios git (que eu já tenho trabalhando), então execute o mesmo checkout git em todos eles. Cada vez que recebo algo assim:

'git rev-list -n 1 --before="2016-04-29 23:59" master'

para alimentar o git checkout. Eu gostaria de passar essa coisa toda para o meu script para que ele possa fazer o checkout para mim. Atualmente, meu script é

#!/bin/bash

echo $1

(Foi inicialmente mais complexo, mas desde então eu comentei todo o resto para que eu possa me concentrar nessa entrada.)

Quando tento executar o script:

./RepoScan 'git rev-list -n 1 --before="2016-04-29 23:59" master'

Eu recebo o seguinte erro:

fatal: Not a git repository (or any of the parent directories): .git

seguido por uma nova linha. Eu suponho que isso significa que o git rev-list está tentando executar, em vez de ser passado para o RepoScan. Existe uma maneira de empacotá-lo para que ele não seja executado quando inserido como um argumento, mas ainda pode ser executado pelo script?

(Além disso, estou usando o OSX, se isso importa.)

    
por Trevor Muraro 08.05.2016 / 03:08

1 resposta

3

Backquotes delimitam uma substituição de comando : o comando dentro das backquotes é executado e sua saída é interpolada na linha de comando. (Existem mais complicações se os retratos posteriores não estiverem entre aspas duplas, mais sobre isso posteriormente.) Então, o que está acontecendo é que git rev-list … é executado no diretório atual, antes que RepoScan seja executado. Não pode ser diferente, pois a saída do comando git é passada como argumentos para RepoScan .

Se você quiser que RepoScan execute um comando que você especificar quando invocá-lo, será necessário passar esse comando na linha de comando de RepoScan , não na saída desse comando. Existem duas maneiras de fazer isso, dependendo do que você quer dizer com comando.

Passando um executável com argumentos

Se o comando for interpretado como um executável com alguns argumentos, passe o comando como uma lista de palavras .

./RepoScan git rev-list -n 1 --before="2016-04-29 23:59" master

Dentro do script RepoScan , use "$@" para se referir ao comando. A notação @ é uma variável especial que representa a lista de argumentos. Quando usado dentro de aspas duplas, tem um comportamento especial: cada argumento é colocado em uma palavra separada, que é o que torna "$@" equivalente à lista de argumentos.

Se o comando RepoScan tiver outras opções, todas elas deverão ser passadas antes do comando. Use o shift incorporado para remover opções processadas desde o início da linha de comando. Normalmente, você usa as opções getopts para analisar.

Passando um fragmento de shell

A outra possibilidade é passar um trecho de programa shell como um único argumento.

./RepoScan 'git rev-list -n 1 --before="2016-04-29 23:59" master'

Observe os dois níveis de cotação desta vez. As aspas simples são para o shell no qual você está chamando RepoScan ; tudo dentro de aspas simples é interpretado literalmente, então RepoScan recebe um argumento que é a string git rev-list -n 1 --before="2016-04-29 23:59" master . Dentro de RepoScan , desde que você tenha um fragmento de shell, execute-o com

eval "$1"

se o snippet estiver no primeiro parâmetro ou

eval "$command"

se o snippet estiver na variável command .

Observe o duplo aspas em torno da expansão da variável . Isso é necessário porque $foo de aspas duplas não significa “o valor de foo ”, mas “pegue o valor de foo , divida-o de acordo com IFS e interprete o resultado como uma lista de padrões globais” (também conhecido como o operador split + glob).

    
por 09.05.2016 / 01:38