各ディレクトリに移動して特定のファイルに対してコマンドを実行するにはどうすればよいですか?

各ディレクトリに移動して特定のファイルに対してコマンドを実行するにはどうすればよいですか?

parent_directoryの各ディレクトリを繰り返し、特定のファイルに対してコマンドを実行するbashスクリプトを作成する方法。

ディレクトリ構造は次のとおりです。

Parent_dir/
  dir1/
   acc.bam
  dir2/
   acc.bam
  dir3/
   acc.bam
... around 30 directories

これが私が使用したいコマンドです:

java8 -jar /picard.jar CollectRnaSeqMetrics REF_FLAT=/refFlathuman.refflat STRAND_SPECIFICITY=NONE I=acc.bam O=output

答え1

一般的な慣用語は

for d in Parent_dir/*/
do
     (cd "$d" && $command)
done

ループforは、.txtファイルの各ディレクトリに対して一度だけ直接実行されますParent_dir。各ディレクトリに対してサブシェルが作成されます。サブシェルからそのディレクトリに変更しようとします(たとえば、十分な権限がないと失敗する可能性があります)、成功した場合はコマンドを実行します。成功するかどうかはcd親シェルに影響を与えないため、間違った場所を心配する必要はありません。


もっと頑丈にしたいなら

    (cd "$d" && test -r acc.bam &&  $command)

acc.bamディレクトリが存在し、読み取り可能であることを確認してください。test -w .書き込み不可能なディレクトリでコマンドを実行したくない場合は、を追加することもできます。


PS上記のどれもBashに限定されません。 /bin/sh はかなり簡単に使用できます。

答え2

.を使用して親ディレクトリのファイルを繰り返しますfor FILE in *; do ...; done。ファイルがディレクトリの場合は、cdそのディレクトリに移動してコマンドを実行してからcd ..

cd $parent_directory
for FILE in *; do
    if [ -d "$FILE" ]; then
        cd "$FILE"
        java8 -jar /picard.jar CollectRnaSeqMetrics REF_FLAT=/refFlathuman.refflat STRAND_SPECIFICITY=NONE I=acc.bam O=output
        cd ..
    fi
done

ディレクトリの変更を避けるために、コマンドにファイル名を使用することもできますI="$FILE/acc.bam"

答え3

あなたがしなければならないのは、parent_directoryの各ディレクトリに行き、javaコマンドを実行することだけです。 parent_directoryに戻るには、次のようにします。

cd ..

parent_directory のディレクトリのリストを取得するには、次のものを使用できます。

find -mindepth 1 -maxdepth 2 -type d

ディレクトリと1つのネストされたレベルのみが一覧表示されます。

ループは次のとおりです。

cmd="java8 -jar /picard.jar CollectRnaSeqMetrics REF_FLAT=/refFlathuman.refflat STRAND_SPECIFICITY=NONE I=acc.bam O=output"
for path in `find -mindepth 1 -maxdepth 2 -type d` 
do
    cd "$path"
    $cmd
    cd ..
done

Javaコマンドは、スクリプトを読みやすくするために別々の変数に配置されます。

答え4

(少なくともBSD、GNU)find実装をサポートすることによって:-execdirsfind

find ParentDir -name acc.bam -execdir \
  java8 -jar /picard.jar CollectRnaSeqMetrics \
  REF_FLAT=/refFlathuman.refflat \
  STRAND_SPECIFICITY=NONE I=acc.bam O=output \;

関連情報