Unixシェルスクリプトですべてのサブディレクトリをトラバースし、何かを実行します


17

シェルスクリプトがメインディレクトリのすべてのサブディレクトリにアクセスするようにします。ディレクトリ内で何かを行い、出力をスプールファイルに送信し、次のディレクトリに移動します。Main Dir = / tmp Sub Dir = ABCD(4つのサブディレクトリ)を考慮してください


2
OK、これまでのスクリプトを見せてください。それのどの部分があなたに問題を与えていますか?
テルドン

回答:


22

forループを使用します。

for d in $(find /path/to/dir -maxdepth 1 -type d)
do
  #Do something, the directory is accessible with $d:
  echo $d
done >output_file

ディレクトリのサブディレクトリのみを検索します/path/to/dir。ディレクトリ名に空白または特殊文字が含まれている場合、上記の簡単な例は失敗することに注意してください。より安全なアプローチは次のとおりです。

find /tmp -maxdepth 1 -type d -print0 |
  while IFS= read -rd '' dir; do echo "$dir"; done

またはプレーンでbash

for d in /path/to/dir/*; do
  if [ -d "$d" ]; then
    echo "$d"
  fi
done

(それに反してfind、ディレクトリへのシンボリックリンクも考慮し、隠されたものを除外することに注意してください)


1
少なくとも、findそのような出力の処理に関連する制限とリスクを指摘してください。
ステファンシャゼラス

こんにちは...私は以下のfor for loop for $(find / backup / ASHISH -maxdepth 1 -type d)do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d
アシッシュ

こんにちは... forループを試しました。for d in $(find / backup / ASHISH -maxdepth 1 -type d)do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d期待される結果はすべてのサブディレクトリからls -ltrです。ループ上で動作していない
アシシュ

1

私は完全にbash初心者ですが、UN * Xのベテランです。間違いなくこれはBashシェルスクリプトで実行できますが、昔はfind [-maxdepth <levels>] <start-dir> -exec <command> ;これを達成するために使用していました。man findおそらく誰かがあなたにそれをする方法をあなたに言うまで、あなたはすることができて、遊ぶことができましたbash


ここでの私の「概要」の回答が賛成票を受け取ったことは非常に光栄です。しかし、以下の@chaosの回答がなぜダウン票を受け取ったのですか?(このボードの新参者として、私は自分の回答に対してのみこのコメントを投稿することはできません。)彼の2番目の提案はシェルスクリプトソリューションに対して正しく、外部findコマンドを実行するオーバーヘッドを回避します。
JonBrave

彼の2番目は確かに正しいです。ディレクトリ名に空白または特殊文字(バックスラッシュなど)が含まれている場合、最初のユーザーは失敗します。安全なバージョンについては、彼の回答に対して行った編集を参照してください。
テルドン

同意する。それは私が称賛していた彼の2番目のシェルのみの回答でした。
JonBrave

私は知っている、私はちょうどダウン票を説明していた(私はそれをキャストしなかった)。
テルドン


1

各サブディレクトリの下にファイル名が必要なようです。ls -l | awkこれらのファイル名が空白および/または改行を含む、どのような場合のために、堅牢で十分ではないのですか?以下は、たまたまそれらのために持っていないs findでも動作します:find-maxdepth

find . ! -name . -type d -prune -exec sh -c '
   cd "$1" && \
   find "." ! -name . -prune  -type f
' {} {} \;

0

私は解決策を得た。以下の検索コマンドは私の要件を満たしています。

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && ls -l |awk '{ print $9 }' |grep `date +"%m%d%Y"`|xargs echo" \;

0

ls、grep、trを使用することもできます

for dir in $(ls -1FA | grep / | tr -d /); do echo $dir/something; done

ls -1FA | grep / | tr -d / | while IFS= read -r TD; do echo $TD/something; done

lsに上記のオプションがない場合は、du / sedをセレクターとして使用することもできます

du --max-depth=1 | sed -e 's/^.*\.\///' | grep -v '\.$'

これらの例が隠しディレクトリを返し、親ディレクトリと現在のディレクトリを除外することに注意することが重要かもしれません


1
(1)標準出力がパイプの場合、デフォルトでlsは1行に1つのファイル(-1オプションで指定されているもの)を  書き込みます(したがって、回答には不要です)。(2)の出力の解析はls悪い考えです。これこれを参照してください。ディレクトリの名前にスペース(または改行)が含まれている場合、最初の回答は失敗し、名前に改行がある場合はすべて失敗します。(3)"$dir"正当な理由がない限り、シェル変数(例えば、)を常に引用する必要があり、自分が何をしているのかを確実に知っている。
スコット

良い点スコット。答えを残して、ひどく名前の付いたdirsのない多くのシステムについては、それがまだ1回限りの役に立つかもしれないと思います。
Jガーツ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.