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

-1

Eu estou tentando contar o número de arquivos dentro de um diretório enquanto verifica os subdiretórios com o mesmo script e soma 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?

user1326293
fonte
Não gostaria de usar returnou unset?
Xen2050

Respostas:

2

Para encontrar o número total de arquivos regulares no diretório $1e em 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 esta linha a partir do código original:

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

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

Em segundo lugar, ao usar variáveis ​​shell $1, eles 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, em 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.

John1024
fonte
Eu sei sobre isso, mas eu ainda estou tentando fazer do meu jeito
user1326293
@ user1326293 Hmm. Acabei de adicionar uma seção que discute alguns dos problemas dessa maneira.
John1024
1

… Não estou obtendo o resultado correto. O que estou fazendo de errado?

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

… Eu ainda estou tentando fazer do meu jeito

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 de diretório, além dos diretórios, enquanto o seu não contará itens que não sejam arquivos simples (por exemplo, links simbólicos, nós de dispositivos, pipes nomeados, soquetes do sistema de arquivos etc.)

(O shopt -s nullglobestá lá para lidar com diretórios que não têm conteúdo).

G-Man
fonte