Chamando o script bash recursivamente com diferentes parâmetros

1

Estou tentando escrever um script que conta todos os arquivos no diretório fornecido & subdiretórios, então eu escrevi isto:

#!/bin/bash

var=0
if ["$#" == "0"]
    directory="$(echo pwd)"
  then
    directory=$1
fi

echo $directory;
for x in 'ls -l $directory | grep "^-" | tr -s ' ' | cut -d ' ' -f 9';
do
var=$((var+1))
done

for x in 'ls -l $directory | grep "^d" | tr -s ' ' | cut -d ' ' -f 9';
do
output = "$($0 $x)"
done

var=$((var+output))
echo $var

Mas eu recebo algo assim:

./lala2
./lala2: line 4: [0: command not found

test
./lala2: line 4: [1: command not found
./lala2: line 4: [1: command not found

Por que isso? As variáveis são globais?

    
por user1326293 10.11.2015 / 02:52

1 resposta

3

Substituir:

if ["$#" == "0"]

com:

if [ "$#" = "0" ]

Alguns comentários:

  1. No shell, os espaços são importantes. Se você quiser que o shell reconheça o comando de teste, [ , deve haver espaços ao redor do [ .

    Os espaços não são importantes para as palavras-chave do shell, mas [ , diferente de [[ , é um comando, não uma palavra-chave.

  2. O significado da mensagem de erro [0: command not found é que "$#" foi avaliado como 0, de modo que a string ["$#" se tornou [0 e bash não encontrou nenhum comando com o nome [0 .

  3. É possível usar == para igualdade de string no bash. Não é, no entanto, portátil. No POSIX, o operador de igualdade correto em [...] é = . Isso se torna muito importante se você executar o script, seja intencionalmente ou involuntariamente , sob um shell POSIX como dash .

Outras questões

  1. Mais uma vez, os espaços são importantes. Quando o shell vê este comando:

    output = "$($0 $x)"
    

    ele tentará executar um comando chamado output e fornecerá dois argumentos, sendo o primeiro = e o segundo o "$($0 $x)" . Consequentemente, como Gordon Davisson aponta, essa linha deve ser substituído por:

    output="$($0 $x)"
    

    Como não há espaços em torno do = , o shell tratará isso como uma atribuição de variável.

  2. O script tenta analisar a saída de ls e isso não é confiável . Nesse caso, isso resultará em erros se algum dos nomes dos subdiretórios contiver espaço em branco.

  3. Como o rici aponta, o comando directory="$(echo pwd)" provavelmente não faz o que você espera. Observe:

    $ directory="$(echo pwd)"
    $ echo "$directory"
    pwd
    

    Esse comando atribui a string pwd à variável directory . Provavelmente, você quer o diretório de trabalho atual, assim:

    directory=$(pwd)
    

    Mas é mais simples que isso. No Unix, o diretório de trabalho atual é sempre . :

    directory=.
    
  4. Existem outras razões pelas quais essa declaração if-then não faz o que se espera:

    if ["$#" == "0"]
        directory="$(echo pwd)"
      then
        directory=$1
    fi
    

    Você provavelmente deseja mover a instrução then e adicionar uma instrução else :

    if [ "$#" = "0" ]
    then
        directory=.
    else
        directory="$1"
    fi
    

Script alternativo

Se o objetivo for contar o número de arquivos regulares em um diretório e todos os seus subdiretórios, tente:

echo "$(find "$directory" -type f -printf "1\n" | wc -l)"

Essa abordagem é segura de usar, mesmo que os nomes de arquivos ou diretórios contenham espaços em branco ou outros caracteres difíceis.

    
por 10.11.2015 / 03:06