配列(応用)

前回の配列と、前々回の変数への代入を使って、簡単なスクリプトを書いてみましょう。
判っている方からしてみると、面倒な事をやってるなー、なんて思うかもしれませんが、今までの部分の復習という意味での使用例みたいなものですから大目にみてやってください。

さて、こんな要件のスクリプトを書いてみます。

・「ls -l」で出力した情報から、「パーミッション」「オーナーグループ」「オーナーユーザ」「ファイルサイズ」「ファイル名」を抜き出す。
・抜き出した情報を、見出しをつけて1行に1項目ずつ出力する。

長ったらしい要件の割には大した事はやってませんが、とりあえず作ってみましょう。

まず、最初に「ls -l」の出力を確認します。

# ls -l
合計 36
-rwxr-xr-x 1 root root   34  3月 16 21:45 helloworld.sh
-rwxr-xr-x 1 root root   55  3月 16 21:45 helloworld2.sh
-rwxr-xr-x 1 root root 1030  3月 16 21:45 helloworld3.sh
-rwxr-xr-x 1 root root  988  3月 16 21:45 helloworld4.sh
-rwxr-xr-x 1 root root  242  3月 16 21:45 helloworld5.sh
-rwxr-xr-x 1 root root  196  3月 16 21:45 helloworld6.sh
-rw-r--r-- 1 root root  193  3月 16 21:45 helloworld7.sh
-rwxr-xr-x 1 root root  374  3月 16 22:20 output02.sh
drwxr-xr-x 2 root root 4096  3月 16 21:46 test01
#

私の環境だと上記の様に出力されました。

     1     2   3    4     5   6   7   8        9
-rwxr-xr-x 1 root root   34  3月 16 21:45 helloworld.sh

これを見ると、「パーミッション」「オーナーグループ」「オーナーユーザ」「ファイルサイズ」「ファイル名」の項目は、
スペース区切りで考えて、それぞれ 1、3、4、5、9の項目だと判ります。

これを踏まえて以下の様なスクリプトを書いてみましょう。

#!/bin/bash

V_LS=`ls -l`

while read LINE
do
        A_LSLINE=(${LINE})
        echo -n "perm    :"
        echo "${A_LSLINE[0]}"
        echo -n "grp     :"
        echo "${A_LSLINE[2]}"
        echo -n "own     :"
        echo "${A_LSLINE[3]}"
        echo -n "size    :"
        echo "${A_LSLINE[4]}"
        echo -n "filename:"
        echo "${A_LSLINE[8]}"
        echo ""
done <<< "${V_LS}"

exit 0

まず、3行目で、「ls -l」の出力を、変数「V_LS」に代入します。

V_LS=`ls -l`

5行目から19行目はループ処理です。

while read LINE
do
        A_LSLINE=(${LINE})
        echo -n "perm    :"
        echo "${A_LSLINE[0]}"
        echo -n "grp     :"
        echo "${A_LSLINE[2]}"
        echo -n "own     :"
        echo "${A_LSLINE[3]}"
        echo -n "size    :"
        echo "${A_LSLINE[4]}"
        echo -n "filename:"
        echo "${A_LSLINE[8]}"
        echo ""
done <<< "${V_LS}"

変数「V_LS」に格納された「ls -l」の出力を1行ずつ取り出し、変数「LINE」に入力してます。
このループのポイントは、19行目の「<<<」にあります。
これは「ヒアドキュメント」の一種で「ヒアストリング」といいます。変数などに格納されている値を
取り出してループ処理を行う際は、変数内に格納されている文字列を一度展開する必要がありますので、
この「ヒアストリング」を使用します。

そして、7行目でコマンド出力を1行読み込んだ変数「LINE」を展開し、配列「A_LSLINE」に格納します。
変数「LINE」にある、スペース区切りの各項目を配列の要素へ格納しますので、変数を「()」でグルーピング
してやります。

A_LSLINE=(${LINE})

最初に確認したとおり、出力対象の項目が1,3.4.5.9にあります。
配列の最初の要素は0からですので、それぞれ、0,2,3,4,8の要素が該当する事になります。
これを順に出力するのですが、今回は見出しを別に出力してみました。面倒であれば、見出しも含めて
1行で出力して構わないです。

さて、このスクリプトを実行してみます。

# ./output02.sh 
perm    :合計
grp     :
own     :
size    :
filename:

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :34
filename:helloworld.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :55
filename:helloworld2.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :1030
filename:helloworld3.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :988
filename:helloworld4.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :242
filename:helloworld5.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :196
filename:helloworld6.sh

perm    :-rw-r--r--
grp     :root
own     :root
size    :193
filename:helloworld7.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :322
filename:output02.sh

perm    :drwxr-xr-x
grp     :root
own     :root
size    :4096
filename:test01

# 

大体想定通りに出力されました。
ただ、一番上の「合計」部分が見栄え悪いですね。
ここの対策もしてみましょう。

一番最初に「ls -l」の出力を確認した時、一番上の行はこんな風に出力されていました。

  1   2
合計 32

この行を配列に格納すると、こんな感じになるはずです。

  0   1
合計 32

と言う事は、配列で言う2番目の要素以降は空だと言う事ですね。
これはこの行以外には当てはまりません。

ですので、こんな感じに修正してみました。

#!/bin/bash

V_LS=`ls -l`

while read LINE
do
        A_LSLINE=(${LINE})
        if [ "${A_LSLINE[8]}" != "" ]
        then
                echo -n "perm    :"
                echo "${A_LSLINE[0]}"
                echo -n "grp     :"
                echo "${A_LSLINE[2]}"
                echo -n "own     :"
                echo "${A_LSLINE[3]}"
                echo -n "size    :"
                echo "${A_LSLINE[4]}"
                echo -n "filename:"
                echo "${A_LSLINE[8]}"
                echo ""
        fi
done <<< "${V_LS}"

exit 0

8行目のif文で、「8番目の要素(ファイル名)が空文字列以外のもの」という条件をつけました。
これによって、ファイル名の要素が無い場合は出力されません。
1行目にはファイル名の要素はありませんので想定通りです。
さっそく実行してみましょう。

# ./output02.sh 
perm    :-rwxr-xr-x
grp     :root
own     :root
size    :34
filename:helloworld.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :55
filename:helloworld2.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :1030
filename:helloworld3.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :988
filename:helloworld4.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :242
filename:helloworld5.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :196
filename:helloworld6.sh

perm    :-rw-r--r--
grp     :root
own     :root
size    :193
filename:helloworld7.sh

perm    :-rwxr-xr-x
grp     :root
own     :root
size    :374
filename:output02.sh

perm    :drwxr-xr-x
grp     :root
own     :root
size    :4096
filename:test01

# 

どうです?
ちゃんと出力されましたでしょうか?