web-dev-qa-db-ja.com

すべてのサブディレクトリに対してシェルスクリプトを実行するためのシェルスクリプト

日常業務を簡素化するためのスクリプトを作成しています。毎日、会社のサーバー内でいくつかのことをgrepする必要があります。大丈夫でしたが、今では、各オブジェクトをサブディレクトリに分離しています。既存のシェルスクリプトが特定のディレクトリ内の各サブディレクトリで繰り返し実行されるソリューションを探しています。どうすればよいですか?私はLinuxにまったく慣れておらず、まだロープを学んでいます。

これが私のスクリプトです:

#!/bin/bash
MainDir=/path/to/dir/containing/subdirs
# cd into dir
cd $MainDir

for dir in $(ls); do

#fetch start time of uut
grep -i "01_node_setup" $dir/his_file | tail -1 >> /home/xtee/sst-logs.out

#check if sysconfig.out exists
if [ -f $dir/sysconfig.out];
then
    grep -A 1 "Drive Model" $dir/sysconfig.out | tail -1 >> /home/xtee/sst-logs.out
else
    grep -m 1 "Pair0 DIMM0" $dir/node0/trans_file_prev/*setupsys* | tail -1 >> /home/xtee/sst-logs.out
fi

done

#cd back to where we started
cd $OLDPWD

ナイスガイがスクリプトを手伝ってくれました。上のスクリプトが出てきました。正常に機能しましたが、sst-logs.outファイルにはgrepの出力の代わりにbinary file /some/subdirectory/が表示されます。スクリプトの何が問題になっていますか?

3
JudeJitsu

検索はあなたを救うでしょう:

find /your/dir/with/subdirs -type d -exec sh -c 'cd "{}" ; /path/to/your/script.sh ;' \;
4
rush

スクリプトにはいくつかの問題があります。

_cd $MainDir
_

これを_cd "$MainDir"_にする方がよいでしょう。ここではこれは重要ではありませんが、入るのは良い習慣です。変数展開を引用符で囲まないままにすると、変数の値が単語に分割され、各単語はシェルワイルドカードパターンとして扱われます。したがって、_$MainDir_に空白または_\[?*_が含まれている場合、このコマンドは失敗します。二重引用符を付けても問題はなく(分割とファイル名の照合を実行したい場合を除く)、これらの余分な拡張を回避できます。コマンド置換($(somecommand))についても同じことが言えます。 分割とファイル名の一致が必要であることがわかっている場合を除き、変数とコマンドの置換は常に二重引用符で囲みます。

_for dir in $(ls); do
_

lsの出力を解析しないでください 。スクリプトにlsが必要になることはほとんどありません。上で説明したように、コマンド置換の結果はワイルドカードパターンとして扱われる単語に分割されるため、$(ls)は、lsが実行する可能性のある印刷不可能な文字のマングリングに加えて、空白文字とワイルドカード文字をマングルします。ディレクトリ内のファイル名の一覧表示は、シェルに組み込まれています。

_for dir in *; do
_

その_for dir in */; do_を作成すると、現在のディレクトリのサブディレクトリのみが一致し、他の種類のファイルは一致しません。

_if [ -f $dir/sysconfig.out];
_

角かっこで囲まれた文字がシェル句読文字である場合を除いて、角かっこの両側に空白が必要です:_();&|<>_。また、変数置換を二重引用符で囲みます(これは、変数置換がある他のすべての場所に当てはまります):_if [ -f "$dir/sysconfig.out" ];_

_#cd back to where we started
cd $OLDPWD
_

これは役に立ちません。プロセスが終了しようとしています。現在のディレクトリを変更しても、何の影響もありません。各プロセスには独自の現在のディレクトリがあることに注意してください。スクリプトでディレクトリを変更しても、スクリプトを呼び出したプログラムには影響しません。


この質問をした理由に目を向けると、何が欲しいのかはっきりしていません。 「_binary file /some/subdirectory/_」はあまり意味がありません。ディレクトリではこのメッセージは表示されません。さらにヘルプが必要な場合は、エラーメッセージをコピーして貼り付けてください。オンラインでヘルプを求めるときは、常にエラーメッセージをコピーして貼り付けてください

あなたの説明から、ファイルは1ディレクトリレベル深く移動したようです。その場合は、行_for dir in */; do_を次のように変更します。

_for dir in */*/; do
_

これを行う方法はたくさんあります。既存のスクリプトをforループで実行するか、findとxargsを使用するか、grepの-r aka --recursiveオプションを使用することもできます。

最も簡単なのは、おそらく既存のスクリプトの周りにforループラッパーを書くことです。例えば:

#! /bin/bash
cd /path/to/top/level/directory

for d in */ ; do 
  pushd $d
  # call your script here
  popd
done
1
cas

@Rushのfind提案を少し改善し、-execスイッチを使用する代わりに、次のようにすることでcdコマンドの追加を回避できます。

find /path/to/dir/containing/subdirs -type d -execdir /path/to/your/script.sh \;

このようにして、元のスクリプトのforループを完全に回避できます。

0