unix講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls...

21
UNIX 講習会 シェルスクリプト 2 31/July /2015 情報管理解析室 西出 浩世

Upload: others

Post on 20-Mar-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

UNIX講習会 シェルスクリプト2

31/July/2015 情報管理解析室 西出 浩世

Page 2: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

シェルスクリプト応用編:

複数ファイルをまとめて処理する

• 条件違いの同じフォーマットのデータが大量にあるとき

• 一件づつコマンドを実行するのは大変

• ヒューマンエラーの元にもなる

• SGEのアレイジョブ機能も使えるが、ごく簡単なコマンド

には少々面倒

• 複数ファイルに対し繰り返し処理をしてくれるシェルスク

リプトの書き方

Page 3: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

作業ディレクトリ~/unix15/sge

$ cd ~/unix15/sge$ ls script*script2.sh script3.sh script4.sh

~/unix15/sge/results  には、sam ファイルが12個入っていることを確認$ ls results/*.sam

入っていない場合は以下のようにコピーしてください

$ rm -r results$ cp -r /usr/local/data/unix15/sge/results .

Page 4: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

for 文•エディタで新しく下記のスクリプトを記述し、script1.sh として保存

•実行権を与えてから実行してみる

#!/bin/shfor sm in results/*.sam do  echo ${sm}done script1.sh

$ chmod +x script1.sh

$ ./script1.sh

results/ecoli.1.samresults/ecoli.10.samresults/ecoli.11.samresults/ecoli.12.sam

$ emacs script1.sh

Page 5: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

繰り返し処理:for文

• 文字列やファイルのリストに対し、順番にある決まった処理をする

• リストはスペース区切りの文字列挙、配列、数字など

• for 後の変数に集合が順番に1つづつ代入され、その後に決まった処理が行われる

• 全ての集合が代入され終わったらfor文も終了

for 変数名 in 文字列などの集合

do   処理

done

for 開始

繰り返しリスト

do 処理

リスト最後?

for 終了 done

Yes

No

Page 6: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

for文に使うリストの例

for i in 1 2 3 4 5 6 7 do…done

for i in {1..10} do…done

for f in ./* do…done

カレントディレクトリ内にある全てのファイル名をワイルドカード「*」を使ってリスト(変数 ${f} にファイル名が1つづつ代入される)

1~7までの整数をリスト(変数 ${i} に1~7が順に代入される)

1~10までの整数をリスト(変数 ${i} に1~10が順に代入される)

Page 7: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

if 文• script2.sh に実行権を与えてから実行してみる

• bowtieの結果ができているかの簡単なチェック

$ chmod +x script2.sh$ ./script2.sh ok

$ less script2.sh

#!/bin/sh if [ -f results/ecoli.10.sam ] then echo 'ok' else echo 'not ok' fi

Page 8: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

• [ ] 内の条件が真か偽か?で処理を変える

• if -> 条件 -> then

• 「if」は必ず「fi」で終わらねばならない

• 条件を複数設定したい場合は「elif」を使う

if [ 条件 ]

then   条件が真だった場合の処理

else   偽だった場合の処理

fi

条件分岐:if 文 if 開始

then 処理

if 終了 fi

True

False if 条件

else 処理

Page 9: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

• 複数の条件を設定:elif

条件分岐:if 文

if [ 条件1 ]

then   処理

elif [ 条件2 ]

then 処理

elif [ 条件3 ]

then 処理

else   全て偽な場合の処理

fi

if 開始

then 処理1

if 終了 fi

True

False if 条件1

else 処理

elif 条件2

then 処理2

True False

Page 10: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

if : 条件判断の演算子• 条件判断の [ ] は、test コマンドの代替表現

• 下記の演算子一覧は man test で見ることができる数値比較数1 -eq 数2 両辺が等しいと真数1 -ne 数2 両辺が等しくないと真数1 -gt 数2 数1 > 数2 の場合に真数1 -lt 数2 数1 < 数2 の場合に真数1 -ge 数2 数1 >= 数2 の場合に真数1 -le 数2 数1 =< 数2 の場合に真

文字列比較

-n 文字列 文字列の長さが0でなければ真

! 文字列 文字列の長さが0なら真

文字列1 = 文字列2 両文字列が同じなら真

文字列1 != 文字列2 両文字列が同じでなければ真

ファイルチェック-d ファイル名 ディレクトリなら真-f ファイル名 通常ファイルなら真-e ファイル名 ファイルが存在すれば真-L ファイル名 シンボリックリンクなら真-r ファイル名 読み取り可能ファイルなら真-w ファイル名 書き込み可能ファイルなら真-x ファイル名 実行可能ファイルなら真-s ファイル名 サイズが0より大きければ真

ファイル名1 -nt ファイル名2 1が2より新しければ真ファイル名1 -ot ファイル名2 1が2より古ければ真

論理結合

! 条件 条件が偽であれば真条件1 -a 条件2 条件1, 2 共真であれば真

条件1 -o 条件2 1, 2 どちらかが真であれば真

Page 11: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

複数のファイル処理

• ~/sge/results/ 内にある12個の .samファイルを .bamファイルに変換したい

✓ samtools の sam -> bam 変換

samtools view -bS example.sam > example.bam

•ファイル名は同じにしつつ、拡張子は「.bam」としたい

Page 12: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

ファイル名を取得するコマンド : basename

•パスからファイル名だけを取り出して表示

•パスとファイル名の末尾から一致する文字列を削除して表示

$ basename ~/unix15/sge/results/ecoli.9.sam

ecoli.9.sam

$ basename ~/unix15/sge/results/ecoli.9.sam .sam

ecoli.9

$ basename ~/unix15/sge/results/ecoli.10.sam 0.sam

ecoli.1

Page 13: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

• date コマンド:現在の日時を表示する

• basenameコマンドと組み合わせてファイル名を変数に記憶する

$ date 2015年 1月 20日 火曜日 11:26:31 JST$ echo "Today is date" Today is date$ echo "Today is `date`" Today is 2015年 1月 20日 火曜日 11:28:08 JST

挟んだコマンドを実行する

バッククォート ` `

$ fn=`basename result/ecoli.9.sam .sam`$ echo ${fn} ecoli.9

Page 14: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

• sam -> bam 変換

• results/ecoli.1.sam を bam に変換し、result/ecoli.1.bam として保存

1) 変数 fn に 「ecoli.1」を記憶しておき、

2) ${fn}.bam という名前でbamファイルを保存

basenameとバッククオートを使って拡張子を変えた同名ファイルを作る

$ fn=`basename results/ecoli.1.sam .sam`

$ echo ${fn}

ecoli.1

$ samtools view -bS results/ecoli.1.sam >

results/${fn}.bam

samtools view -bS example.sam > example.bam

1)

2)

Page 15: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

for文, basename , ` ` を使って取得したファイル名を確認する

• ワイルドカード「*」を使って、results 内にある全ての .sam

ファイルをリスト

• ${sm} , ${fn} にはどんな文字が入るか?

$ less script3.sh

for sm in results/*.sam do fn=`basename ${sm} .sam` echo ${sm} ${fn} done script3.sh

$ chmod +x script3.sh$ ./script3.sh

Page 16: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

演習• for文を使って ~/unix15/sge/results/ 内の全 .samファイルを .bamに変換する

✓ samtools の sam -> bam 変換

samtools view -bS example.sam > example.bam    

✓ script3.sh を改変して作ること

✓ .bam ファイルも results/ 内に保存すること

✓結果のファイル名は、ecoli.1.bam ~ ecoli.12.bam にすること

✓ basename と バッククォートを使いましょう

✓ qsub する前にsamtoolsコマンド全体を echo で出力してみましょう

✓テストは ./script3.sh で実施し、echo が上手くいったらechoを除いてqsub script3.sh してみてください

Page 17: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

演習 途中経過

script5.sh

#!/bin/sh

for sm in results/*.sam

do

fn=`basename ${sm} .sam`

echo “samtools view -bS ${sm} > results/${fn}.bam”

done

$ ./script3.sh

Page 18: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

演習 解答

script5.sh

#!/bin/sh

#$ -cwd

for sm in results/*.sam

do

fn=`basename ${sm} .sam`

samtools view -bS ${sm} > results/${fn}.bam

done

$ qsub script3.sh

Page 19: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

• 名前または数値のリスト:「配列」を作り、記憶しておく

• 配列名=(リスト…) で作成

• $ { 配列名 [ リスト番号 ] } で各リストの値を呼び出す

シェルスクリプトにおける「配列」

$ array=("human" "mouse" "rat")$ echo ${array} human$ echo ${array[2]} rat$ echo ${array[@]}  配列全てを表す human mouse rat

$ fl=(results/*.sam)$ echo ${fl[0]}

$ fl=(`ls`)$ echo ${fl[@]}

カレントディレクトリのファイル名リストを配列に

results/ 内の.samで終わるファイル名リストを配列に

human� mouse� rat�

0,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,2�

Page 20: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

for文に配列を与え、番号で取り出す

•ワイルドカード「*」を使って、results 内にある全ての .sam ファイルを配列 ${array} に記憶させる

•ファイルは12個あることがわかっているので、1~12 のリストで内容を取り出すが、配列の番号は0から始まるので 1 を引いている

• for i in {0..11} として 1 を引かなくても良い

#!/bin/sh

array=(results/*.sam)

for i in {1..12}

do

fn=`basename ${array[i-1]} .sam`

echo $fn ${array[i-1]}

done

Page 21: UNIX講習会 シェルスクリプト2作業ディレクトリ ~/unix15/sge $ cd ~/unix15/sge $ ls script* script2.sh script3.sh script4.sh ~/unix15/sge/results には、sam ファイルが12個入っていることを確認

バッククォート、配列をアレイジョブに応用

ファイル名に連続した数字が付いていなくてもアレイジョブにリストを与えることができる

配列の番号は0から始まるが、SGE_TASK_ID に入るのは1からなので 1を引いている  ${list[${SGE_TASK_ID}-1]}

#!/bin/sh#$ -t 1-12#$ -cwd

list=(`ls ../rnaseq/test_fastq/`)

bowtie2 -x ../rnaseq/ecoli_genome -U ../rnaseq/test_fastq/${list[${SGE_TASK_ID}-1]} -S results/ecoli.${SGE_TASK_ID}.sam

script4.sh