bashのgetoptsについて

bashでバッチ処理を書く際に便利なのがgetopts

例えば

batch.sh -f aaa.txt -d 20080829

って感じで引数を処理したい場合


#!/bin/bash

OPTIONS="f:d:"

while getopts $OPTIONS opt $@
do
case $opt in
"f") filename=$OPTARG ;;
"d") date=$OPTARG ;;
*) exit -1;;
esac
done

って感じで処理できる


関数に引数を渡す形で配列内にある値に対して処理を行うサンプルを作ってみた

test1.sh


#!/bin/bash

OPTIONS="f:i:"

aryItems=(a.txt b.jpg c.pdf)
aryItemCD=(100 200 300)

main() {
unset filename
unset image_cd
while getopts $OPTIONS opt $@
do
case $opt in
"f") filename=$OPTARG ;;
"i") image_cd=$OPTARG ;;
*) exit -1;;
esac
done

echo "filename:$filename"
echo "image_cd:$image_cd"

if [ $filename ]; then
if [ $image_cd -ne 0 ]; then
return 0
else
echo "ERROR $OPTERR [ image_cd:$image_cd ]" 1>&2
return -1
fi
else
echo "ERROR $OPTERR [ file:$filename image:$image_cd ]" 1>&2
return -1
fi
}

echo "count:["${#aryItems[*]}"]"

j=0
cnt=0
for i in ${aryItems[*]}
do
j=${aryItemCD[$cnt]}
let cnt=$cnt+1
echo "+------------------------------------------------------------+"
echo "LOOP : $cnt ARGV : -f $i -i $j"
main -f $i -i $j
sleep 1
done

exit 0;

aryItems内にあるファイル名をループしてmain関数に渡し処理する

実行


count:[3]
                                                                                                                          • +

LOOP : 1 ARGV : -f a.txt -i 100
filename:a.txt
image_cd:100

                                                                                                                          • +

LOOP : 2 ARGV : -f b.jpg -i 200
filename:
image_cd:
ERROR 1 [ file: image: ]

                                                                                                                          • +

LOOP : 3 ARGV : -f c.pdf -i 300
filename:
image_cd:
ERROR 1 [ file: image: ]

あれ?

2回目以降がダメだ!

main関数内のgetoptsしてるループでshiftしてみる


count:[3]
                                                                                                                          • +

LOOP : 1 ARGV : -f a.txt -i 100
filename:a.txt
image_cd:
./test1.sh: line 25: [: -ne: unary operator expected
ERROR 1 [ image_cd: ]

                                                                                                                          • +

LOOP : 2 ARGV : -f b.jpg -i 200
filename:
image_cd:200
ERROR 1 [ file: image:200 ]

                                                                                                                          • +

LOOP : 3 ARGV : -f c.pdf -i 300
filename:
image_cd:
ERROR 1 [ file: image: ]

あらら、そっか2回目のループの値にshiftしてるのね

main関数とOPTIONS="f:i:"を外部ファイルにしてみる

test2.sh


#!/bin/bash

aryItems=(a.txt b.jpg c.pdf)
aryItemCD=(100 200 300)

echo "count:["${#aryItems[*]}"]"

j=0
cnt=0
for i in ${aryItems[*]}
do
j=${aryItemCD[$cnt]}
let cnt=$cnt+1
echo "+------------------------------------------------------------+"
echo "LOOP : $cnt ARGV : -f $i -i $j"
./main.sh -f $i -i $j
sleep 1
done

exit 0;


main.sh


#!/bin/bash

OPTIONS="f:i:"

main() {
unset filename
unset image_cd
while getopts $OPTIONS opt $@
do
case $opt in
"f") filename=$OPTARG ;;
"i") image_cd=$OPTARG ;;
*) exit -1;;
esac
done

echo "filename:$filename"
echo "image_cd:$image_cd"

if [ $filename ]; then
if [ $image_cd -ne 0 ]; then
return 0
else
echo "ERROR $OPTERR [ image_cd:$image_cd ]" 1>&2
return -1
fi
else
echo "ERROR $OPTERR [ file:$filename image:$image_cd ]" 1>&2
return -1
fi
}

main $@

exit 0

で、実行


shell> ./test2.sh
count:[3]
                                                                                                                          • +

LOOP : 1 ARGV : -f a.txt -i 100
filename:a.txt
image_cd:100

                                                                                                                          • +

LOOP : 2 ARGV : -f b.jpg -i 200
filename:b.jpg
image_cd:200

                                                                                                                          • +

LOOP : 3 ARGV : -f c.pdf -i 300
filename:c.pdf
image_cd:300

おお!!うまくいった!!!

内部に定義した関数だとなんでダメなんだろ

う〜ん、分からん

時間あるときに調べよ