EDIT: desculpe. esta é minha primeira pergunta aqui.
Aqui está um exemplo mínimo de trabalho
#!/bin/bash
#
count=0
function something() {
if test -f "$1"; then
# is a file
((count++))
echo $count $1
elif test -d "$1"; then
# is a folder
find $1 | while read line; do
if [ $1 != $line ]; then # first line in find is the folder itself. prevent infinte recursion
something $line
fi
done
fi
}
while [ $# -gt 0 ]
do
something "$1"
shift
done
echo "Processed $count files"
Exemplo de saída:
$ ./test.sh *
1 0/file1.txt
2 0/file2.txt
1 1/file1.txt
2 1/file2.txt
1 2/file1.txt
2 2/file2.txt
1 3/file1.txt
2 3/file2.txt
1 4/file1.txt
2 4/file2.txt
1 5/file1.txt
2 5/file2.txt
1 6/file1.txt
2 6/file2.txt
1 7/file1.txt
2 7/file2.txt
1 8/file1.txt
2 8/file2.txt
1 9/file1.txt
2 9/file2.txt
1 test.sh
Processed 1 files
Como você pode ver, cada vez que chamo a função recursivamente, ela retorna ao estado da variável na função pai e bagunça a contagem.
Usando o Ubuntu 22.06 na VM WSL2
Eu entendi certo que você quer contar todos os arquivos em uma árvore de diretórios, ou algo assim? Ou seja, você quer que a variável
count
seja global?Seu problema está aqui:
Vê esse pipeline? O que os pipelines fazem é iniciar dois ou mais processos em paralelo , e fazer isso requer iniciar processos distintos no nível do SO. O que o shell faz aqui ao clonar a si mesmo. Esses clones não podem afetar o processo pai, então a variável é efetivamente localizada, e quando o pipeline termina, você obtém o valor original de volta.
Veja Por que minha variável é local em um loop 'while read', mas não em outro loop aparentemente semelhante? para soluções para isso.
Como exemplo, uma função recursiva normal:
executando que imprime:
Agora, altere a
func
linha interna para egecho | func $(( $1 + 1 ))
e você verá a contagem diminuir novamente quando a função chamar return.Agora, outra coisa completamente diferente é que chamar
find
cada nível de um tree walk recursivo é um pouco suspeito, já quefind
ele mesmo irá recursivamente percorrer toda a árvore. Tem certeza de que quer adicionar outro walk em cima disso? Isso levará a diretórios sendo processados várias vezes.Se voltarmos a contar arquivos, você poderia fazer isso com apenas um
find
, por exemplo:embora isso contaria nomes de arquivo com quebras de linha como arquivos múltiplos. Com o GNU find, você poderia usar
... -printf x | wc -c
para evitar isso.Na verdade, basta remover a recursão manual para chamar uma função para cada arquivo (normal):
(use
find ... -print0 | while IFS= read -r -d '' file; do ...
no Bash para evitar problemas com quebras de linha em nomes de arquivos)