こんにちは、キクです。
今日はとあるシェルスクリプトを書きました。
今の会社に入社した頃、研修でシェルスクリプトを書く機会がありました。
その時の感情は、「難しい。でも嫌いじゃないぞ」でした。
自分で考えた組み合わせが上手く噛み合ってスクリプトが走った時、ある種の気持ち良さがあります。
しかし、それ以来あまりコマンド自体に触れることが少なく、いろんなことを忘れていってしまいます。
そんな状態でしたが、今日久しぶりにスクリプトを書いたのでブログに残します。
やりたかった動作
・あるディレクトリA配下に存在するディレクトリB~D全てにテストファイルを作成
・ディレクトリ名B~Dは変数に代入し、「ディレクトリ名.txt」というテストファイル名にする
事前環境
失敗例1
想定
1. [ name ]という変数に、[ ls -l /A ]の実行結果を代入
2. [ echo test >> /A/$name/$name".txt" ]の[ $name ]部分に[ B ]が代入される
3. [ /A/B ]配下にテストファイル[ B.txt ]が作成される
4. 以降[ $name ]部分に[ C ]および[ D ]が代入され、同様の処理が行われる
実際の動き
1. [ name ]という変数に、[ ls ] [ -l ] [ /A ]が代入され、以降の処理が始まる
2. [ echo test >> /A/$name/$name".txt" ]の[ $name ]部分に[ ls ]が代入される
3. [ /A/ls ]配下にテストファイル[ ls.txt ]を作成しようとする
4. 実際には[ /A ]配下に[ /ls ][ -l ] [ /A ]ディレクトリは存在しないので、「/lsいないよ」と怒られる
何が起こったのか?
[ ls -l /A ]がそれぞれ[ ls ] [ -l ] [ /A ]という文字列として認識され、それが順次[ $name ]に代入されてしまった
失敗例2
改善点
[ ls -l /A ]を[ ` ` ]で囲むことで、1つの塊として認識させました
想定
失敗例1の想定と同様
実際の動き
上図の[ ls -l /A ]の実行結果である[ total ] [ 0 ] [ drwxr-xr-x. ] ・・・[ D ]が[ $name ]に代入されました。
想定していない動きであり、不要な処理がたくさん走ってしまいました。
何が起こったのか?
[ ls -l /A ]の実行結果それぞれが文字列として認識され、順次[ $name ]に代入されてしまいました。
成功例
改善点
1. まず[ grep -v total ]により、不要なtotal行を排除
2. [ cut -f 9 --delim " " ]により、必要な[ B ] [ C ] [ D ]部分だけ切り取る
※[ -f ]:フィールドを指定
[ 9 ]:9番目のフィールド
[ --delim "空白" ]:空白をフィールドの区切りとする
drwxr-xr-x.2rootroot6Jun2122:26B
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨
実行結果
上記の第9フィールドのみを切り出せたことにより、[ B ] [ C ] [ D ]が順次[ $name ]に代入されました。
その結果
[ /A/B ]配下にテストファイル[ B.txt ]
[ /A/C ]配下にテストファイル[ C.txt ]
[ /A/D ]配下にテストファイル[ D.txt ]
を作成することができました。
おわりに
コマンド結果を変数に代入する際には、結果のどの部分を代入したいのかを明確にし、その部分を必要に応じて切り出してあげることが必要なのだと学びました。
シェルスクリプトって書いているときは複雑に感じるのですが、完成してみると意外と「やっていることはシンプルだな」と感じることがある気がします。
今後はもっと自分の引き出しを増やしていきたいなともいます。
ではでは。