トップページunix
1001コメント285KB

シェルスクリプト総合 その2

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2005/04/17(日) 00:17:17
シェルスクリプトの総合スレです。スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>1-10くらい)をご覧ください。

□前スレや過去スレ:
シェルスクリプト総合 その1
http://pc8.2ch.net/test/read.cgi/unix/1101820646/
☆シェルスクリプトを勉強するにあたって☆
http://pc5.2ch.net/test/read.cgi/unix/989659936/
便利なシェルスクリプト見せろ
http://pc5.2ch.net/test/read.cgi/unix/996949546/
【貝】第1回シェル講座【殻】
http://fun.kz/test/read.cgi/unix/1016372780/

□関連スレ:
sed
http://pc8.2ch.net/test/read.cgi/unix/1085730992/
おまえら! shell は何を使っているんですか?
http://pc5.2ch.net/test/read.cgi/unix/1012330865/
Eshell の使い方とか設定とか【Emacs Shell、Lisp】
http://pc8.2ch.net/test/read.cgi/unix/1102921590/

□他板の関連スレ:
Macでシェルスクリプト総合 Part 1
http://pc7.2ch.net/test/read.cgi/mac/1105074933/
【Shell】どのシェル使ってる?【Script】
http://pc8.2ch.net/test/read.cgi/linux/1067330754/
0210名無しさん@お腹いっぱい。2005/05/23(月) 22:00:39
他人の書いたシェルを読んでたら
何してるかわからない箇所が出てきて困ってます(>_<)
これってどう解釈したら良いの?
ファイル名の何かをピリオドと比較してるようだけど・・・
詳しくは何してるのかなぁ

#!/bin/sh
filename=$1
if[ "${filename%${filename#?}}"="." ] ; then
0211名無しさん@お腹いっぱい。2005/05/23(月) 22:21:22
>>209
man sh して、Parameter Expansion の項を参照せよ。
0212名無しさん@お腹いっぱい。2005/05/23(月) 22:28:19
先頭が '.' で始まっているかどうか判別してるんじゃねえの?
# expr を使わずに、shell の中だけでやるあたりが。。。
0213名無しさん@お腹いっぱい。2005/05/23(月) 22:34:08
#!/bin/sh
for name in *;do
echo ${name%${name#?}}
echo $name
done

これを実行するとわかってしまう。
0214名無しさん@お腹いっぱい。2005/05/23(月) 22:35:53
${filename:0:1} ってbash固有なの?
/bin/sh がなくって試せないや。
0215名無しさん@お腹いっぱい。2005/05/23(月) 23:01:56
>>214
sh にはないね。Bad substitution エラーになりますた。
0216名無しさん@お腹いっぱい。2005/05/23(月) 23:18:39
${filename:0:1}はbash独自だが、
${name#?}や${name%xxx}も、
巣の/bin/shでは使えない。

ファイル名の先頭が.かどうかを判断するなら、

case "$filename" in
.*)
hoge;;
esac

でやるべきだな。
これなら移植性抜群。
0217名無しさん@お腹いっぱい。2005/05/24(火) 00:20:30
PSコマンドとgrepを利用し、特定のプロセスをkillしたいのですが、
プロセスid(pid)をうまく取得する方法はありますか。

何桁目で取得しているのですが、うまくいかずに困っています。
アドバイスお願いいたしまし。
0218名無しさん@お腹いっぱい。2005/05/24(火) 00:29:11
>>217
pgrep(1) で出来ると思うけど、そのままずばり pkill(1) 使えば?
Solaris 由来のコマンドだけど、最近の Linux にも入ってるらしい

シェルスクリプトでやりたいなら、ps(1) の出力を read(1) で
読んで処理すれば良いと思う

ps -ef | grep [m]y_command | read i j k; kill -9 $i

# i j k は適当。man 読んでね
0219名無しさん@お腹いっぱい。2005/05/24(火) 00:37:54
>>218
スマソ. こっちが正解

ps -ef | grep [m]y_command | while read uidx pidx rest; do kill -9 ${pidx}; done
0220名無しさん@お腹いっぱい。2005/05/24(火) 01:10:55
>>217,218,219
ps -o pid,command
0221名無しさん@お腹いっぱい。2005/05/24(火) 01:29:27
>>209
それって[ ]の中が引数1つだから常に真のような気がするが。
0222名無しさん@お腹いっぱい。2005/05/24(火) 02:02:32
>>221
grep [m]y_command は、my_commandにはマッチさせて
grep自身にはマッチさせないための常套手段。

んでも、grep '[m]y_command' みたいにクォートしないとダメかも。
0223名無しさん@お腹いっぱい。2005/05/24(火) 02:11:09
>>222
そういう話ではない。
02242182005/05/24(火) 02:11:32
>>222
多分レス番違ってる...

bash はシングルクォートで囲わなくてもオッケーでした
zsh はダメみたい

デフォで囲っておくかエスケープした方が良かったですね
訂正サンクス
0225名無しさん@お腹いっぱい。2005/05/24(火) 19:24:08
zshまで、考える必要はない。
0226名無しさん@お腹いっぱい。2005/05/24(火) 20:32:56
この場合はzshかどうかの問題じゃない。
たまたまカレントディレクトリに、
my_command
という名前のファイルが存在していると、
grep [m]y_command
を実行しても、シェルによって
grep my_command
に展開されてしまい、せっかくの用をなさなくなる。
なので、基本的には常にシングルクォートを使って
grep '[m]y_command'
とするものと覚えた方がいい
0227名無しさん@お腹いっぱい。2005/05/24(火) 20:45:52
>たまたまカレントディレクトリに、

なんでやねん。
アホか。
0228名無しさん@お腹いっぱい。2005/05/24(火) 20:53:50
>>226
おお、なるほど! こういうの、意外に見つけにくい盲点だよな。
作った時は動いたのに、ある日突然動かなくなるシェルスクリプトは、
原因が [m] とかの展開にあったりする。
カレントディレクトリはどこになるかわからないから、
こういう名前のファイルはない、とか、仮定しちゃいけないね。

>>227
あなたの方がアホですね。
0229名無しさん@お腹いっぱい。2005/05/24(火) 21:30:11
grep
file指定がない場合、標準入力からの読み込みのはずだが?
0230名無しさん@お腹いっぱい。2005/05/24(火) 21:34:16
>>229
Hah?
grepが起動される前に、[m]y_commandという文字列が
シェルによって、カレントディレクトリと照合されて
展開されてしまうことを問題にしているわけだが?
頭大丈夫?
0231名無しさん@お腹いっぱい。2005/05/24(火) 21:43:37
話の流れが読めてないよね
0232名無しさん@お腹いっぱい。2005/05/24(火) 21:54:36
[m] という文字列は、
シェルにとってはファイル名展開(ワイルドカードの一種)
grepにとっては正規表現であること、
および、シェルの引数解釈とコマンド実行の順序関係について、

>>227 = >>229 は理解していないと見た。
0233名無しさん@お腹いっぱい。2005/05/24(火) 22:01:15
>>224
間違ってないっしょ。
0234名無しさん@お腹いっぱい。2005/05/24(火) 22:34:42
>>233
ゴミンナサイ
221 は 209 の test コマンドに対して突っ込み入れてるのかと
思ってたけど違うか
0235名無しさん@お腹いっぱい。2005/05/24(火) 22:45:37
説明しよう。

221 は 209 の testコマンドの = の両側にスペースがないことに
突っ込みを入れた。(この突っ込みは正しい)


222 は、221が自分への突っ込みかと誤解した。
しかし、その後、222が [m]y_command の意味について
説明していること自体は正しい。

上記の2つは全然別の話題。
0236名無しさん@お腹いっぱい。2005/05/24(火) 22:53:41
ナルホド、ありがとう。
ちなみに 222 != 218 です。自分が 218, 219 なので。
02372212005/05/25(水) 00:42:17
>>235
ワロス

全然話が噛み合ってないと思ったらそういうことか。[]が紛らわし
かったのね。
0238名無しさん@お腹いっぱい。2005/05/25(水) 01:56:43
よく読みといたな。バグでも探すみたいだ。
0239名無しさん@お腹いっぱい。2005/05/28(土) 16:08:43
すみません。ちょっとご教授願いたいのですが、

シェルスクリプトで
--------------------------------------
YYYY/MM/dd HH*MM:SS AAAAAAAAA BBBBBBB
CCCCC DDDDD
YYYY/MM/dd HH*MM:SS AAAAAAAAA BBBBBBB
CCCCC DDDDD
--------------------------------------
こういう形のログがある場合に
--------------------------------------
YYYY/MM/dd HH*MM:SS AAAAAAAAA BBBBBBB CCCCC DDDDD
YYYY/MM/dd HH*MM:SS AAAAAAAAA BBBBBBB CCCCC DDDDD
--------------------------------------
こういう風に直したいのですが、どのようにすればいいのですか?
要するに改行を取り除きたいのですが・・・。
0240名無しさん@お腹いっぱい。2005/05/28(土) 16:16:56
>>239
シェルスクリプトでもreadを使えばできるが、
普通はsedを使った方が楽。
よって、sedスレで質問しなさい。

http://pc8.2ch.net/test/read.cgi/unix/1085730992/l50
0241名無しさん@お腹いっぱい。2005/05/28(土) 16:18:13
239はマルチ
0242名無しさん@お腹いっぱい。2005/05/28(土) 16:19:25
>>239
cat log |sed -ne "N; s/\n/ /; p;"
0243名無しさん@お腹いっぱい。2005/05/28(土) 16:20:41
>>239
必ず2行単位で並んでいて、
その改行を取るだけなら、


while read a_line
do
 echo -n "$a_line"
 read b_line
 echo "$b_line"
done
0244名無しさん@お腹いっぱい。2005/05/28(土) 16:26:46
>>241
どことのマルチか書かないと。
0245名無しさん@お腹いっぱい。2005/05/28(土) 16:31:19
すいません、Solarisスレで最初聞いてしまいました。
こちらに誘導されましたので、こちらで質問させていただきました。
>>242殿、>>243殿 ありがとうございました。
0246名無しさん@お腹いっぱい。2005/05/28(土) 16:37:06
>>245
移動したなら元スレにそう書いといてくれよ。
0247名無しさん@お腹いっぱい。2005/05/28(土) 17:58:29
それにしたって、誘導しといてマルチ呼ばわりする必要ないだろ。
礼儀の足りないやつだとでも心の中で思っとけ。
0248名無しさん@お腹いっぱい。2005/06/02(木) 19:50:43
# clear; while :; do echo -n "^[[1;1H"; netstat -nr; sleep 1; done
   (ttp://codezine.jp/a/article.aspx?aid=67 より)
上のスクリプトのechoの部分は、「echo "^[[1;1H"として画面左上隅にカーソルを
移動させる」とあります。
しかし、bash(2.05b)で動かしてみましたが、^[[1;1Hが表示されるだけです。
何が問題なのでしょうか?
0249名無しさん@お腹いっぱい。2005/06/02(木) 20:07:40
>>248
^[ をどうやって打ち込んだか
0250名無しさん@お腹いっぱい。2005/06/02(木) 20:19:10
echo -ne "¥e[1;1H"
0251名無しさん@お腹いっぱい。2005/06/02(木) 22:08:39
tput crまたはecho -e '\r'の方がいいと思われ。
0252名無しさん@お腹いっぱい。2005/06/02(木) 22:09:01
すまん。echo -ne '\r'だった
02532512005/06/02(木) 22:13:48
さらに、ごめん。出力は1行じゃないのね。じゃあ毎回clearでもい
いと思うが。
0254名無しさん@お腹いっぱい。2005/06/02(木) 22:18:46
>>253
そういう話じゃなくて>>249ってだけだと思うが
0255名無しさん@お腹いっぱい。2005/06/02(木) 22:30:21
>>254
すまん。
0256名無しさん@お腹いっぱい。2005/06/03(金) 14:01:33
tput cup 0 0
0257名無しさん@お腹いっぱい。2005/06/03(金) 17:29:18
OSを特定できないヘテロな環境(POSIXは仮定できる)で
ファイルのサイズを取得するのはどうすればいいのでしょう?

ls -lのサイズのカラムは決まっていないようですし、
-sオプションの振舞いも微妙に異なるので困ってます。
0258名無しさん@お腹いっぱい。2005/06/03(金) 17:35:19
>>257
stat(2)
02592572005/06/03(金) 17:42:10
>>258
シェルスクリプトの中でcc起動してってことでしょうか?
Cのコードを書くとなると、そこでまたポータビリティに気を
使ったりしなきゃならないので、なるべく避けたいです。

wc呼ぶぐらいなら、Cのコードで行くとは思いますが...
0260名無しさん@お腹いっぱい。2005/06/03(金) 17:45:51
昔のSolarisだとccがついてこなかったような。
0261名無しさん@お腹いっぱい。2005/06/03(金) 18:42:01
stat(1)でいいじゃん
02622572005/06/03(金) 19:08:53
>>261
stat(1)のない古めのOSもあるんです。

POSIX標準の話を付け加えれば、stat(1)は標準にないようです。
0263名無しさん@お腹いっぱい。2005/06/03(金) 19:21:44
とりあえず進む。ダメな環境にぶち当たった時点で個別に考える。
0264名無しさん@お腹いっぱい。2005/06/03(金) 22:06:44
>>259
なんでwc嫌なの? wcだってfstatしてるだけじゃない。
0265名無しさん@お腹いっぱい。2005/06/04(土) 00:40:25
>264
どのUNIXでも、wc -cはfstatするの?
02662652005/06/04(土) 00:51:41
Solaris 9 はreadの繰り返し。
Red Hat Linux 9 は fstat64
FreeBSD 4.xはfstat
0267名無しさん@お腹いっぱい。2005/06/04(土) 14:40:08
> wc呼ぶぐらいなら、Cのコードで行くとは思いますが...
じゃあスレ違いなんでどっか行ってください。
0268名無しさん@お腹いっぱい。2005/06/04(土) 17:50:01
ファイルサイズもまともに取れないOSって糞ですね
0269名無しさん@お腹いっぱい。2005/06/04(土) 19:23:01
>>268
必死だなw
0270名無しさん@お腹いっぱい。2005/06/04(土) 23:41:27
関数を呼び出してその戻り値をある変数に入れたいのですがどうやればいいのか分りません。

    VAL=func1()

としただけでは
line 3: syntax error near unexpected token `('
となってしまいます。
0271名無しさん@お腹いっぱい。2005/06/04(土) 23:45:31
func1
VAL=$?
0272名無しさん@お腹いっぱい。2005/06/04(土) 23:49:47
>>271
ありがとうございます。さすがシェルスクリプトですね。ダサすぎますw
PerlやRubyが流行るのも分るような・・・
0273名無しさん@お腹いっぱい。2005/06/04(土) 23:57:14
>>271 で取得出来るのは終了ステータスだが、それで良いのか?
インタラクティブ用途がメインの言語にケチ付けるのもアレだな
0274名無しさん@お腹いっぱい。2005/06/04(土) 23:57:37
関数呼び出しに()はいらないよ
0275名無しさん@お腹いっぱい。2005/06/05(日) 00:10:23
>>273>>274
関数内でreturnした値が得られたみたいです。
$ function hello(){ return 3;};hello;echo $?
3
ただし、returnできる値はunsigned charに限られるようで、
0〜255までの値しか返せませんでした。ここは注意しないとダメっぽいです・・・

あともう一つお願いします。
$ if [ echo ];then echo "true";fi
true
$ if [ echo "abc" ];then echo "true";fi
bash: [: echo: unary operator expected

これはどうしてなんでしょうか?
0276名無しさん@お腹いっぱい。2005/06/05(日) 00:18:39
>>275
>unary operator expected

って書いてある通り
0277名無しさん@お腹いっぱい。2005/06/05(日) 00:39:38
$ if(echo "abc"&&date);then echo "true";fi
abc
Sun Jun 5 00:39:09 JST 2005
true

testをやめて()にしたら、なぜだかいきました。
でも()ってたしかサブシェルの起動だったような・・・よくわからん
0278名無しさん@お腹いっぱい。2005/06/05(日) 00:45:13
if echo "abc";then echo "true";fi
ってどうなるかわかる?
0279名無しさん@お腹いっぱい。2005/06/05(日) 00:55:16
>>277
なんか基本的な部分が分かってない気がする。
とりあえず、man testしてみなさい。
0280名無しさん@お腹いっぱい。2005/06/05(日) 01:08:54
いや、たぶん man sh をじっくり読むべきじゃないかな。
それが bash なら test の説明もあるし。

>>272
Perl や Ruby よりもシェルスクリプトが勝る点は、
どんなアホにもすぐに書き散らかすくらいのことは出来るようになるってこと
だからしょうがないよ。がんばれ。
0281名無しさん@お腹いっぱい。2005/06/05(日) 01:08:59
man sh だろ。
0282名無しさん@お腹いっぱい。2005/06/05(日) 01:09:45
>>279
test(1)の中の記述で、

  (expression) True if expression is true.

というものがあるんですが、これはなんでしょう?

>>278
ifというのは「以下に続くコマンドを実行した、その終了ステータスを
判定する」ということなのですね。
$ if cat /etc/password > /dev/null 2>&1;then echo "true";else echo "false";fi
false
$ if [ -z `cat /etc/password` ];then echo "true";else echo "false";fi
cat: /etc/password: No such file or directory
true

先のif(echo "abc"〜では、起動したサブシェルの終了ステータスを
判定していたということですか。なるほど。
0283名無しさん@お腹いっぱい。2005/06/05(日) 01:11:25
>Perl や Ruby よりもシェルスクリプトが勝る点は、
>どんなアホにもすぐに書き散らかすくらいのことは出来るようになるってこと
〜よりも〜が の用法が逆です。
0284名無しさん@お腹いっぱい。2005/06/05(日) 01:21:54
あと最初に戻って、
$ test echo
$ test ! echo
これらがなんのメッセージも出さないのはちょっと謎です。
まあどうでもいいか。
0285名無しさん@お腹いっぱい。2005/06/05(日) 01:45:59
>>284
うちの man test には以下の記述があります。

s1 True if s1 is not the null string.

なんのメッセージも出さないのは、そもそも echo が実行されないからですね。
0286名無しさん@お腹いっぱい。2005/06/05(日) 03:13:50
>>282
括弧を付けてもいいってこと。まあ普通は付けない
>>284
test echoはtest hogeと同じ
0287名無しさん@お腹いっぱい。2005/06/05(日) 03:48:56
>>265
しない例を挙げてください
0288名無しさん@お腹いっぱい。2005/06/05(日) 04:13:41
(´・ω・`)
0289名無しさん@お腹いっぱい。2005/06/05(日) 13:09:11
>>288 ハゲワロス 壺にハマッタ〜 (゜∀。)ワヒャヒャヒャヒャヒャヒャ
0290名無しさん@お腹いっぱい。2005/06/06(月) 22:14:47
真か偽か、コレの表示出すにはどないしたらええの?
0291名無しさん@お腹いっぱい。2005/06/06(月) 22:17:07
echo 真か偽か
0292名無しさん@お腹いっぱい。2005/06/06(月) 22:40:07
test hoge && echo 真 || echo 偽
0293名無しさん@お腹いっぱい。2005/06/09(木) 23:15:07
/var/qmail/bin/maildir2mbox && exec elm ${1+"$@"}
この ${1+"$@"} ってどういう意味?
0294名無しさん@お腹いっぱい。2005/06/09(木) 23:41:09
本家 Bourne シェルにあったバグを避けるおまじない。
詳しい意味はUNIXプログラミング環境に書いてあった
希ガス
0295名無しさん@お腹いっぱい。2005/06/10(金) 07:25:39
本家Bourne shellの系統と思われるSolaris/SunOSの/bin/shでさえ、
${1+"$@"}と書く必要はなかったよ。
(引数ゼロ個の場合、"$@"は空文字列にならず、完全に消えてくれる)

今時、"$@"でいいんじゃないか?
逆に、${1+"$@"}と本当に書かなきゃならないshが存在するOSを
教えてくれ。
0296名無しさん@お腹いっぱい。2005/06/10(金) 08:24:03
つくればあるもーん
0297名無しさん@お腹いっぱい。2005/06/10(金) 09:42:11
ハッキングから、消防のたわごとまで、これが うにっx クオリティ
0298名無しさん@お腹いっぱい。2005/06/10(金) 22:27:08
sed の d と D の違いを教えてください。
>d
> パターンスペースを削除する。次のサイクルを開始する。
>D
> パターンスペースの最初の改行までを削除する。次のサイクルを開始するが、パターンスペースにまだデータが残っていたら、入力からの読み込みをスキップする。
0299名無しさん@お腹いっぱい。2005/06/10(金) 22:33:39
>>298
sedはsedスレへ
http://pc8.2ch.net/test/read.cgi/unix/1085730992/l50
0300名無しさん@お腹いっぱい。2005/06/14(火) 23:20:41
1時間に10000個のファイルを消そうとしているのですが
forで回してひとつひとつ消すと
時間はかかるけどvmstatで表示されるidが95 をキープする。
forのなかで5個ずつ消すと
時間はかからないけどidが90を切っちゃう。

時間かけず、idを高く保って、大量のファイルを削除する方法ありますきあ?
0301名無しさん@お腹いっぱい。2005/06/14(火) 23:24:24
xargs
0302名無しさん@お腹いっぱい。2005/06/14(火) 23:31:43
>>300
idって何よ。priorityあるいはniceか?どっちにしてもエスパーな質問だな……
0303名無しさん@お腹いっぱい。2005/06/14(火) 23:47:02
>>302
vmstatコマンドを打つとcpuのしたにus,sy,idと表示されますよね?
idleだとおもいます。
0304名無しさん@お腹いっぱい。2005/06/15(水) 00:16:38
思いますじゃなくてmanを嫁。
0305名無しさん@お腹いっぱい。2005/06/15(水) 00:24:48
idle timeだよね
0306名無しさん@お腹いっぱい。2005/06/15(水) 05:12:02
>>300
ファイルを削除ディレクトリに移動してディレクトリごと削除
0307名無しさん@お腹いっぱい。2005/06/15(水) 09:32:12
>>306
移動の時に同じ質問が
時間かけず、idを高く保って、大量のファイルを移動する方法ありますきあ?
0308名無しさん@お腹いっぱい。2005/06/15(水) 10:09:42
そもそも何でそんな馬鹿げた要求が出てきてるのかわからんなぁ。
idle を増やしたいなら、ファイル消すたびに sleep 10 とかしたら?

>forのなかで5個ずつ消すと

rm file1; rm file2; ... と rm file1 file2 ... で
だいぶ違うわけだがどっちよ?
0309名無しさん@お腹いっぱい。2005/06/15(水) 20:21:21
借鯖とかでキャップされてるんじゃないの
■ このスレッドは過去ログ倉庫に格納されています