Я попытался с этой строкой, начиная с родительской папки, содержащей папки, которые я хочу просмотреть:

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

Но он просто выводит все содержимое всего моего компьютера и возвращается в корневую папку /~ ... какое-нибудь объяснение этому поведению?

1 ответ1

4

Поведение bash умолчанию "globbing" (подстановка / расширение подстановочных знаков) состоит в том, чтобы возвращать само выражение подстановочного знака, если подстановочный знак ничего не соответствует. Так что если вы cd - диск в каталог , который не имеет подкаталоги, вы в конечном итоге пытается cd в буквальном смысле «* /» (буквально каталог, имя которого звездочка), и это не получится , так что вы будете оставаться один каталог выше чем вы думали, что окажетесь в этой точке цикла. Поэтому, когда вы cd .. , вы снова окажетесь на один каталог выше. В конце концов вы вернетесь на корневой уровень вашей файловой системы.

Многие сценарии оболочки предпочитают использовать find(1) а не циклы оболочки, когда они хотят, чтобы скрипт прошел по дереву каталогов. Весь ваш фрагмент сценария станет:

find . -type d

... или, если вы действительно хотели абсолютные пути, а не относительные пути:

find "$PWD" -type d

Если вы хотите придерживаться циклов оболочки для этого, вы можете попробовать что-то вроде этого:

#!/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

Обратите внимание, как я использовал операторы if для проверки каждого значения dir и dir2 чтобы убедиться, что они действительно являются каталогами, и я пропускаю их, если это не так.

Также обратите внимание на строку set -evx , которая представляет собой хороший набор опций, которые нужно установить, когда вы впервые пишете / отлаживаете скрипт:
-e останавливается на первой ошибке.
-v печатает каждую строку перед тем, как ее выполнить.
-x печатает каждую строку после выполнения всех различных подстановок / расширений перед ее выполнением.

Также подумайте о том, чтобы потратить некоторое время на справочной странице bash(1) рассматривая такие параметры оболочки, как nullglob и failglob , если вам не нравится поведение по умолчанию для подстановки, когда возвращается само подстановочное выражение, когда оно не соответствует никому.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .