ファイルを一覧表示するための再帰シェルスクリプト

ファイルを一覧表示するための再帰シェルスクリプト

ディレクトリ(およびサブディレクトリ)にある特定の種類のファイルを一覧表示するシェルスクリプトを作成しようとしています。再帰部分のために苦労しています。

これが私が持っているものです:

#!/bin/sh

#download dir
DOWNLOADING_DIR=/Users/richard/Downloads

echo "Starting Script..."

for FILE in $DOWNLOADING_DIR/*
do
    if [ -d "$FILE" ]
    then
        echo "...Checking Directory "$FILE
        for DFILE in $FILE/*
        do
            echo "Found file ... $DFILE"
        done
    else
        echo "Found file ... $FILE"
        echo ""
    fi
done

問題は、ディレクトリを見つけるときにディレクトリ内のファイル名が見つからないことです。サブディレクトリのファイルではなく、サブディレクトリ名のみが一覧表示されます。最初のディレクトリのファイルに対して機能します。

.txtまたは.docファイルを検索して別のディレクトリに移動するには、このスクリプトが必要です。

ベストアンサー1

あなたのスクリプトはいいえ自分を呼び出さないので再帰的です。

同様のものを再帰的に実装するバリアントは次のとおりです。

#!/bin/bash

walk_dir () {
    shopt -s nullglob dotglob

    for pathname in "$1"/*; do
        if [ -d "$pathname" ]; then
            walk_dir "$pathname"
        else
            printf '%s\n' "$pathname"
        fi
    done
}

DOWNLOADING_DIR=/Users/richard/Downloads

walk_dir "$DOWNLOADING_DIR"

この関数はwalk_dirディレクトリパス名を唯一の引数として使用し、その内容を繰り返します。ディレクトリが見つかったら、サブディレクトリをナビゲートするために自分自身を再帰的に呼び出します。

.txtファイル名または末尾のファイルを見つけるには、このコマンドを変更してください.doc

#!/bin/bash

walk_dir () {    
    shopt -s nullglob dotglob

    for pathname in "$1"/*; do
        if [ -d "$pathname" ]; then
            walk_dir "$pathname"
        else
            case "$pathname" in
                *.txt|*.doc)
                    printf '%s\n' "$pathname"
            esac
        fi
    done
}

DOWNLOADING_DIR=/Users/richard/Downloads

walk_dir "$DOWNLOADING_DIR"

上記の「ファイル」は、実際にはディレクトリやディレクトリのシンボリックリンクではなく、すべてを意味し、ディレクトリと同じではないかもしれません。一般ファイル。でdotglobおよびnullglobシェルオプションを設定すると、bash隠しパス名を見つけることができ、潜在的に空のディレクトリを特別にテストする必要はありません。

これのバリエーションは/bin/sh隠された名前を気にしません。

#!/bin/sh

walk_dir () {
    for pathname in "$1"/*; do
        if [ -d "$pathname" ]; then
            walk_dir "$pathname"
        elif [ -e "$pathname" ]; then
            case "$pathname" in
                *.txt|*.doc)
                    printf '%s\n' "$pathname"
            esac
        fi
    done
}

DOWNLOADING_DIR=/Users/richard/Downloads

walk_dir "$DOWNLOADING_DIR"

globstarexglobシェルオプションを使用すると、次のようbashに(再帰なしで)ファイルを移動することもできます。

shopt -s globstar extglob

mv "$DOWNLOADING_DIR"/**/*.@(txt|doc) "$destdir"

...結果ファイルのリストが長すぎない限り。**パス名のスラッシュと一致し(で有効globstar*.@(txt|doc)、またはで終わるすべてのファイル名と一致します.txt.docで有効extglob)。


特定の最上位ディレクトリ内または下に終わるファイル名を持つ一般的なファイルを見つけて、.txt別のディレクトリに移動するより効率的で移植可能な方法です。.doc$topdir$destdir

find "$topdir" -type f \( -name '*.txt' -o -name '*.doc' \) \
    -exec mv {} "$destdir" \;

GNUを使用すると、mvより効率的にすることができます。

find "$topdir" -type f \( -name '*.txt' -o -name '*.doc' \) \
    -exec mv -t "$destdir" {} +

この変更は移行されます。一括一度に1つのファイルの代わりにファイル。mvwithを使用して-v移動した内容を確認するか、beforeを追加してという名前のパス名の-printリスト-execを取得します。mv

おすすめ記事