Um script bash para chamar a si mesmo e retornar um valor

-1

Estou tentando contar o número de arquivos dentro de um diretório enquanto verifico os subdiretórios com o mesmo script e somar os resultados.

#!/bin/bash

var=0

var=$(ls -l $1 | grep "^-" | tr -s ' ' | cut -d ' ' -f 9 | wc -l)

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

No entanto, não estou obtendo o resultado correto.

O que estou fazendo de errado?

    
por user1326293 19.11.2015 / 23:48

2 respostas

2

Para encontrar o número total de arquivos regulares no diretório $1 e seus subdiretórios:

find "$1" -type f -printf "1\n" | wc -l

Para salvar esse número em uma variável:

var=$(find "$1" -type f -printf "1\n" | wc -l)

Isso funcionará mesmo que os nomes de arquivos ou diretórios contenham espaços em branco ou outros caracteres difíceis.

Discussão

Vamos considerar essa linha do código original:

 for x in 'ls -lr $1 | grep "^d" | tr -s ' ' | cut -d ' ' -f 9';

Primeiro, deve-se nunca analisar ls . Não é confiável. A saída de ls muda de uma versão para a próxima. Além disso, devido à maneira como os caracteres especiais são tratados, o nome exibido por ls não é necessariamente o nome correto do arquivo ou diretório.

Em segundo lugar, ao usar variáveis shell, como $1 , elas devem estar entre aspas duplas. Caso contrário, a divisão de palavras e a expansão do nome de caminho são executadas nelas, o que pode levar a todos os tipos de erros.

Em terceiro lugar, de uma forma como:

for x in '...'

o shell executará a divisão de palavras e a expansão do nome de caminho no resultado da substituição do comando. Isso também pode levar a todos os erros.

    
por 19.11.2015 / 23:54
1

… I’m not getting the right result.  What am I doing wrong?

  1. eu não sei; seu script funciona para mim (em testes muito limitados).
  2. John1234 discute problemas com sua abordagem.

… I’m still trying to do it my way

Aqui está uma adaptação do seu script que funciona (para mim) e usa mecanismos mais seguros:

#!/bin/bash

var=0
shopt -s nullglob

for x in "$1"/*
 do
      if [ -d "$x" ]
      then
            output="$($0 "$x")"
            var=$((var+output))
      else
            var=$((var+1))
      fi
 done
echo $var

Isso é diferente do seu, em que o meu contará todas as entradas do diretório, diferente de diretórios, enquanto o seu não contará coisas que não são arquivos simples (por exemplo, links simbólicos, nós de dispositivos, pipes nomeados, soquetes do sistema de arquivos, etc.)

(O shopt -s nullglob está lá para manipular diretórios sem conteúdo.)

    
por 20.11.2015 / 05:18