ディレクトリ(およびサブディレクトリ)にある特定の種類のファイルを一覧表示するシェルスクリプトを作成しようとしています。再帰部分のために苦労しています。
これが私が持っているものです:
#!/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"
globstar
exglob
シェルオプションを使用すると、次のよう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つのファイルの代わりにファイル。mv
withを使用して-v
移動した内容を確認するか、beforeを追加してという名前のパス名の-print
リスト-exec
を取得します。mv