Como posso testar um arquivo com um valor?

2

Estou usando

source ~/.rvm/scripts/rvm
repos="repo_1_ruby_193 repo_2_ruby_211 repo_3_ruby_191"
> rvm_check.txt
for repo in $repos
do
  cd ~/zipcar/$repo 2>rvm_check.txt
  cd ..
  echo $repo
  if [ -z 'cat rvm_check.txt | grep not' ] # line 9
    then
      echo "YES"
    else
      echo "NO"
      exit 1
  fi  
done

e está funcionando principalmente, mas eu recebo:

$ ./multi_repo_rubies.sh 
repo_1_ruby_193
YES
repo_2_ruby_211
YES
repo_3_ruby_191
./multi_repo_rubies.sh: line 9: [: too many arguments
NO
$

se eu tento -s ou -z

Estou recebendo o SIM / NÃO que desejo, mas como evitar o erro [: ?

    
por Michael Durrant 22.11.2014 / 23:48

2 respostas

5

Substituir:

if [ -z 'cat rvm_check.txt | grep not' ]

Com:

if ! grep -q not rvm_check.txt

O motivo para usar test em uma instrução if é porque ela define um código de saída que o shell usa para decidir ir para a cláusula then ou else . grep também define um código de saída. Consequentemente, não há necessidade de teste, [ , aqui. grep define o código de saída para sucesso (0), se encontrou a cadeia. Você quer sucesso se a string não for encontrada. Assim, negamos o resultado do código de saída usando ! .

Explicação

O comando de teste, [ , espera que uma única sequência siga -z . Se o comando grep produzir mais de uma palavra, o teste falhará com o erro que você viu.

Como exemplo, considere este arquivo de amostra:

$ cat rvm_check.txt
one not two

A saída de grep se parece com:

$ cat rvm_check.txt | grep not
one not two

Quando test é executado, todas as três palavras aparecem dentro do [...] , fazendo com que o comando falhe:

$ [ -z 'cat rvm_check.txt | grep not' ]
bash: [: too many arguments

Isto é o mesmo que se você tivesse digitado:

$ [ -z one not two ]
bash: [: too many arguments

Uma solução para isso é usar aspas duplas:

$ [ -z "'cat rvm_check.txt | grep not'" ]

As aspas duplas impedem que o shell execute divisão de palavras . Como resultado, a saída de grep aqui é tratada como uma única string, não dividida em palavras separadas.

No entanto, como grep define um código de saída sensato, não há necessidade de teste, conforme mostrado na linha recomendada acima.

Comentários adicionais

  • O formulário atualmente preferido para substituição de comando é $(...) . Enquanto os backticks ainda funcionam, eles são frágeis. Em particular, os backticks não podem ser aninhados.

  • Nos comandos que usam nomes de arquivos no comando, o uso de cat é desnecessário. Em vez de:

    cat somefile | grep something
    

    Use apenas:

    grep something somefile
    
por 23.11.2014 / 00:00
0

Acabei usando:

if [ -f ~/.rvm/scripts/rvm ]; then
  . ~/.rvm/scripts/rvm
else
  echo
  echo --- FAIL ---
  echo
  echo "You do not have a standard RVM install, cannot procede"
  echo "Please install rvm locally and re-run this program"
  exit 1
fi
repos="repo_3_ruby_191 repo_1_ruby_193 repo_2_ruby_211"
for repo in $repos
do
  if [ ! -f ~/zipcar/$repo/.ruby-version ]; then
    echo
    echo --- WARN ----
    echo
    echo No .ruby-version file present for $repo
    echo This *might* be an issue if there are ruby, e.g. rspec, tests.
    echo If so, please add and commit a .ruby-version file to $repo
    echo
  else
    version=$(cat ~/zipcar/$repo/.ruby-version)
    echo Checking ruby version: $version for repository: $repo"..."
    cd ~/zipcar/$repo 2>rvm_check.txt.$$
    if grep -qi 'not installed' ../rvm_check.txt.$$; then
      echo
      echo --- FAIL ---
      echo
      echo The required ruby version for $repo was not present on this machine
      echo Please install it with
      echo
      echo "  "RVM install $version
      echo
      echo and then re-run this program
      echo
      exit 1
    else
      echo $version Installed
    fi  
  fi  
done
echo
echo All required ruby versions verified as present through RVM
    
por 23.11.2014 / 02:06

Tags