Faz loop por diretórios e subdiretórios no bash

0

Eu tentei com esta linha, começando na pasta pai que contém as pastas pelas quais eu quero fazer um loop:

for dir in */; do  
    cd $dir  
    for dir2 in */; do  
        cd $dir2  
        ls -d $PWD/*  
        cd ..  
    done  
    cd ..  
done

Mas apenas mostra todo o conteúdo do meu computador inteiro e volta para a pasta raiz / ~ ... qualquer explicação para esse comportamento?

    
por hirschme 14.09.2018 / 00:42

1 resposta

4
O comportamento "globbing" (correspondência / expansão de caractere curinga) de

bash é retornar a expressão curinga em si, se o caractere curinga não corresponder a nada. Então, se você cd em um diretório que não tem subdiretórios, você vai acabar tentando cd literalmente '* /' (literalmente um diretório cujo nome é um asterisco), e isso irá falhar, então você fique um diretório maior do que você pensou que você estaria neste ponto no loop. Então, quando você, em seguida, cd .. , você será um diretório maior novamente. Eventualmente, você voltará para o nível raiz do seu sistema de arquivos.

Muitos gerenciadores de script optam por usar find(1) em vez de loops de shell quando desejam que um script passe por uma árvore de diretórios. Todo o seu trecho de script se tornaria:

find . -type d

... ou, se você realmente quisesse caminhos absolutos em vez de caminhos relativos:

find "$PWD" -type d

Se você quiser manter loops de shell para isso, tente algo assim:

#!/bin/bash
set -evx
for dir in */; do
    if [ -d "$dir" ]; then
        cd "$dir"
        for dir2 in */; do
            if [ -d "$dir2" ]; then
                cd "$dir2"
                ls -d "$PWD"/*
                cd ..
            fi
        done
        cd ..
    fi
done

Note como usei as instruções if para testar cada valor de dir e dir2 para garantir que sejam realmente diretórios, e eu os pulo se não forem.

Observe também a linha set -evx , que é um bom conjunto de opções para definir quando você está gravando / depurando um script pela primeira vez:
-e pára no primeiro erro.
-v imprime cada linha antes de executá-la.
-x imprime cada linha após todas as várias substituições / expansões foram executadas, antes de executá-la.

Considere também gastar algum tempo na página bash(1) man analisando as opções de shell como nullglob e failglob , se você não gostar do comportamento padrão de globbing de retornar a própria expressão curinga quando ela não corresponder a nada .

    
por 14.09.2018 / 01:37

Tags