トップページ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/
0374名無しさん@お腹いっぱい。2005/06/22(水) 23:32:43
>>373
お前、古典の成績よくなかっただろw
0375名無しさん@お腹いっぱい。2005/06/23(木) 00:36:40
何で古典が関係あんの?
0376名無しさん@お腹いっぱい。2005/06/23(木) 00:51:40
>>374
お前、現国の成績よくなかっただろw
0377名無しさん@お腹いっぱい。2005/06/23(木) 01:53:22
fj. が通じない世代なのね。。。はぁ・・・。
0378名無しさん@お腹いっぱい。2005/06/23(木) 01:59:20
fj世代はいい年こいてゆがんだ性格がまだ直らないようだな
0379名無しさん@お腹いっぱい。2005/06/23(木) 09:52:15
いい年こいてるから直んないんだよ
0380名無しさん@お腹いっぱい。2005/06/23(木) 19:04:30
Musical Baton というチェーンメールの blog 版をもらった。
ファイルシステム内の音楽ファイルの容量を得るスクリプトキボン。
0381名無しさん@お腹いっぱい。2005/06/23(木) 19:19:14
> Musical Baton というチェーンメールの blog 版をもらった。
TrackBack といい、これといい、なんで blog 界の奴らはこんな糞なことしか思い付かないのか。
0382名無しさん@お腹いっぱい。2005/06/23(木) 23:52:08
bashでの質問です

vmstatの出力結果を5秒毎にファイルに記録してます
vmstat 5 > vmstat_log

記録状況を確かめようとtail -fして監視してみたんですが

どうも途中でバッファリングされているのか20行程まとめて出力が一気に記録されます
vmstatのソースをみたんですが、コマンド自体は出力を毎回フラッシュしているようです

バッファリングされずに5秒毎にリアルタイムに記録したいのですが、
方法はあるんでしょうか
0383名無しさん@お腹いっぱい。2005/06/24(金) 00:05:15
>>382
俺のところではそれでちゃんと5秒くらいごとに一行ずつ表示される。
少なくともbashとは何の関係もないな。
システム依存のスレにいったほうがいい。
0384名無しさん@お腹いっぱい。2005/06/24(金) 00:05:41
スレ違い
0385名無しさん@お腹いっぱい。2005/06/24(金) 00:05:52
>>382
フラッシュしてるのにフラッシュされないってどんな環境?
0386名無しさん@お腹いっぱい。2005/06/24(金) 00:41:36
>>382
tailの-fオプションって、入力が標準入力(パイプ)の時は無視されるんちゃう?
FreeBSDやGnu(やLinux)のtailだとmanにそうかいてあるけど。
03873862005/06/24(金) 00:43:18
>>386
超スマン、これ勘違い。
書き込んだファイルをtail -fしたってことか。
0388名無しさん@お腹いっぱい。2005/06/24(金) 10:37:16
>>386
> 書き込んだファイルをtail -fしたってことか。

それだけじゃなくて、

> tailの-fオプションって、入力が標準入力(パイプ)の時は無視されるんちゃう?

これ、書き方が変だよ。
「入力が標準入力(パイプ)の場合に無視される」んじゃなくて、
「入力(標準入力)がパイプの場合に無視される」でしょ。
例えば「tail -f <vmstat_log」の場合、入力は標準入力だけど、
パイプじゃないから無視されないでしょ。

>>382
OSはなに?
NetBSD で
vmstat 5 >vmstat_log &
tail -f vmstat_log
を実行すると、ちゃんと1行ずつ表示されるよ。
vmstatのソースを読んだOSと、vmstatを実行しているOSが違っていて、
実行している方のOSのvmstatでは、毎行のfflush(stdout)がないん
じゃない?
03893822005/06/25(土) 01:16:44
みなさん御意見ありがとうございます

>>388
OSはRedHatEL3.0です

ちょっとどこのソースをみていたかを確認してみます

ちなみに今手元に環境がないのでcygwinで試したところ同様の現象が起きました
こちらのソースもみてみます・・・


0390名無しさん@お腹いっぱい。2005/06/26(日) 10:09:57
\n で flush されるから、普通いちいち fflush(stdout) なんてしないでしょ?
0391名無しさん@お腹いっぱい。2005/06/26(日) 12:11:34
>>390
man stdio
0392名無しさん@お腹いっぱい。2005/06/26(日) 13:12:51
出力先がファイルのときは\nでflushされない罠
0393名無しさん@お腹いっぱい。2005/06/26(日) 16:49:12
>>333,334 OSは何?
0394名無しさん@お腹いっぱい。2005/06/27(月) 10:50:08
>>390
つ[APUE 2nd Edition]
0395名無しさん@お腹いっぱい。2005/06/27(月) 11:47:03
下記のスクリプトで、
なぜcutはsortの出力のみを処理するのですか?
どうやってcatの出力とsortの出力を区別しているのですか?

#!/bin/sh
cat a.txt |
if [ "$MAILCHECK" = 10 ]
then
sort b.txt | cut -d, -f1
sed 's/hoge/fuga/'
else
sed 's/foo/bar/'
fi
0396名無しさん@お腹いっぱい。2005/06/27(月) 12:55:31
>>395
区別なんかしてない。標準入力を見ているだけだ。パイプによって
標準入力は sort の出力と結び付けられている
0397名無しさん@お腹いっぱい。2005/06/27(月) 13:40:53
よく分かりません。
パイプによって標準入力はsortの出力と結びつけられている。
さらに、catの出力とも結びつけられている。
というように思えます。
catとsortの出力が混じり合ったものをcutが処理すると
予想していましたが、catの出力がsedに渡っているよう
なので混乱しています。

もしかして
1. cutの標準入力にsortの出力を結びつける
2. その結び付きを解除する
3. sedの標準入力にcatの出力を結び付ける
4. その結び付きを解除する
という手順なのでしょうか?

0398名無しさん@お腹いっぱい。2005/06/27(月) 14:13:37
cutの入力にはsortの出力が設定されている。だからsortの出力を処理する。
sedの行では特に入力は明示されていない。だからcatの出力をそのまま処理する。
0399名無しさん@お腹いっぱい。2005/06/27(月) 16:00:12
なんとなく分かりました
パイプについてもっと勉強します
ありがとうございました
0400名無しさん@お腹いっぱい。2005/06/27(月) 16:26:21
man sh あたりにパイプラインについて書いてない?
0401名無しさん@お腹いっぱい。2005/06/27(月) 18:09:56
デケデケデケデケ
0402名無しさん@お腹いっぱい。2005/06/27(月) 20:08:50
キュッキュッ
0403名無しさん@お腹いっぱい。2005/06/28(火) 17:07:24
AIX の sh だけど特定のファイルのタイムスタンプを取得する良い方法はありますか?
ls の結果を解析すれば取れるだろうけどもそっとスマートなやり方はないかな?
0404名無しさん@お腹いっぱい。2005/06/28(火) 17:16:53
>>403
Linuxだけど stat -c %y <file> で last modified を取得してまつよ
でも、表示が冗長なので他にも方法があれば知りたいところ
0405名無しさん@お腹いっぱい。2005/06/28(火) 17:44:57
perl -e '@stat=stat("/"); print localtime($stat[9]) . "\n";'
0406名無しさん@お腹いっぱい。2005/06/29(水) 14:28:09
>>403
またお前か。
0407名無しさん@お腹いっぱい。2005/06/29(水) 16:06:58
>>406
まるち?
0408名無しさん@お腹いっぱい。2005/07/06(水) 00:00:30
dirA/hoge01_1.txt
dirA/hoge01_2.txt
dirA/hoge01_10.txt
dirA/hoge01_11.txt
があった時に、find . -name "*.txt" して、この順番で表示させたいのですが、
やってみると、FreeBSDのfindだと期待通り表示されますが、cygwin の find
だと

dirA/hoge01_1.txt
dirA/hoge01_10.txt
dirA/hoge01_11.txt
dirA/hoge01_2.txt

と表示されてしまいます。これを上のように表示させる良い方法はないでしょうか?
find の出力を sort -t "_" -k2 とかやってもうまくいきませんでした。
0409名無しさん@お腹いっぱい。2005/07/06(水) 00:12:29
文字列でソートしたら下のようになるよね。lsもそうなる。linux
でfindしたら上になった。
0410名無しさん@お腹いっぱい。2005/07/06(水) 00:12:49
>>408
_と.で区切れ。
0411名無しさん@お腹いっぱい。2005/07/06(水) 00:20:48
find は見つかった順に出力されるから、
同じマシンであってさえ、ファイルの作成した時期とかによって
出力の順番が異なることがありうるぞ。
04124082005/07/06(水) 00:34:58
>>409-410
どうもです。

とりあえず sort -n -t "_" に通したら、うまくいきますた。

>>411
ということは、>>408の上のように表示されてもそれはたまたま
なので、sort に通した方が良さそうですね。
0413名無しさん@お腹いっぱい。2005/07/06(水) 00:45:35
>>410
sort でセパレータを2つ指定できるの?

>>412
「-k」を指定しないなら「-t」は不要だと思う。
その例なら「-n」だけでうまくいくんだろう。
ただ、「-n」は数値以外のフィールドでソートする場合(今回の場合)、
動作は保証されないと思う。
0414名無しさん@お腹いっぱい。2005/07/06(水) 10:37:35
man見る限りsortのセパレータは正規表現じゃないな
0415名無しさん@お腹いっぱい。2005/07/06(水) 13:10:33
シェルでファイルの拡張子以外の部分(正確にはピリオドより前の部分)
を取得する方法をおしえてくださいませ。

for i in `ls *txt`
do
cat $FILE.txt | 適当な処理 > $FILE.doc
done

みたいなことをしたい。
前もって、foo だけを取得して、$FILE=foo としたい。。。
0416名無しさん@お腹いっぱい。2005/07/06(水) 13:13:55
FOO=`basename $i .txt`
0417名無しさん@お腹いっぱい。2005/07/06(水) 13:15:53
ああ、なんかめちゃくちゃや。。。
訂正。

for in `ls *txt`
do
ここで、$FILE にファイルのピリオドより前の部分を突っ込みたい。
cat $i | 適当な処理 > $FILE.doc
done
0418名無しさん@お腹いっぱい。2005/07/06(水) 13:17:19
>>415
> for i in `ls *txt`
for i in *txt じゃだめなん?
0419名無しさん@お腹いっぱい。2005/07/06(水) 14:24:30
bashなら${i%.???}
http://www.linux.or.jp/JM/html/GNU_bash/man1/bash.1.html#lbAZ

sedなら sed 's/¥.[^¥.][^¥.][^¥.]$//'
0420名無しさん@お腹いっぱい。2005/07/06(水) 14:53:56
>>417
ふつー、basenameだろ。

FILE=`basename "$i" .txt`
cat "$i" | 適当な処理 > "$FILE".doc

さらにいうとcatも要らんな。

FILE=`basename "$i" .txt`
適当な処理 < "$i" > "$FILE".doc

で桶。
ファイルネームが含まれる場合、いつも" "で囲う癖を付けた方がいいよ。
04214172005/07/06(水) 15:54:41
みなさんありがつ。

basename って初めてしったよ。。。

>>420
ファイルネームが含まれるときは、"" で囲った方がいいのは、
なんでかしらん? ようわからん。。。
0422名無しさん@お腹いっぱい。2005/07/06(水) 16:19:18
シェルが困っちゃうような文字列が含まれてることあるじゃん?
0423名無しさん@お腹いっぱい。2005/07/06(水) 21:49:30
>>421
シェルスクリプトなら、/etc とか /bin の下にあるのを
参考にすると勉強になると思うよ。
0424名無しさん@お腹いっぱい。2005/07/07(木) 23:45:15
時々コマンドをフルパスで書いているスクリプトを見かけるのですが、
何か意味があってそうしてるんでしょうか?
0425名無しさん@お腹いっぱい。2005/07/07(木) 23:53:10
alias 切られてたり、PATH 変数によって意図したコマンドと違う物が起動したら嫌でしょ
0426名無しさん@お腹いっぱい。2005/07/07(木) 23:54:09
PATHをセットするのが面倒だから,とか?

ちがうな。。。。
0427名無しさん@お腹いっぱい。2005/07/07(木) 23:57:08
cron から起動するんだろ。まぁ /bin の下のとかは必要ないが統一性をもたせるためにとか。
0428名無しさん@お腹いっぱい。2005/07/08(金) 00:09:38
秒単位のファイルの更新時刻ってどうやったらわかんの?
ls -lだと分までしかでないんだけど。
0429名無しさん@お腹いっぱい。2005/07/08(金) 00:11:54
stat(3C)
0430名無しさん@お腹いっぱい。2005/07/08(金) 00:35:50
おっけー。
あんがと。
0431No Gnus is good news2005/07/08(金) 00:41:35
>>428
perl -e '@stat=stat("/"); print localtime($stat[9]) . "\n";'
0432No gnus is bad news2005/07/08(金) 00:53:18
foo=/usr/local/bin/emacs
emacs --batch --eval '(princ (format-time-string "%r\n" (nth 5 (file-attributes "'$foo'"))))'
冗談です^^;;
0433名無しさん@お腹いっぱい。2005/07/08(金) 09:30:44
stat にオプションが効かねえええ

と思ったら zsh は stat が builtin なのね orz
0434名無しさん@お腹いっぱい。2005/07/08(金) 09:31:12
つか date -r ./hoge でわかった。
でもお前らいろいろありがとうな。
0435名無しさん@お腹いっぱい。2005/07/08(金) 10:13:57
solaris$ date -r /tmp
date: illegal option -- r

だせぇー。やっぱGNU date必須だな。
0436名無しさん@お腹いっぱい。2005/07/08(金) 10:20:07
FreeBSD% date -r /tmp
usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ...
[-f fmt date | [[[[[cc]yy]mm]dd]HH]MM[.ss]] [+format]
0437名無しさん@お腹いっぱい。2005/07/08(金) 10:39:16
% date -r 1000000000
Sun Sep 9 10:46:40 JST 2001

個人的にはこれができる FreeBSD の date の方が GNU date より重宝する。
GNU date でもできなくはないんだけどさ。

% date -d "$(($(date +%s) - 1000000000)) seconds ago"
Sun Sep 9 10:46:40 JST 2001
0438名無しさん@お腹いっぱい。2005/07/08(金) 10:42:40
>>433
どの zsh よ?
0439名無しさん@お腹いっぱい。2005/07/08(金) 14:01:07
>>435
GNU者うざい。
0440名無しさん@お腹いっぱい。2005/07/08(金) 14:13:00
>>439
(゚Д゚)ハァ?
0441名無しさん@お腹いっぱい。2005/07/08(金) 15:55:26
>>437
その目的ならおれはこれでいいや。
perl -e 'print scalar localtime 1000000000'
0442名無しさん@お腹いっぱい。2005/07/09(土) 00:40:44
GNU の ls だったら --full-time が使える。
書式は --time-style で好きなように
0443名無しさん@お腹いっぱい。2005/07/09(土) 01:12:54
bash で質問です。

> cat hoge.txt
20050708 aaa AAA
20050709 bbb BBB
20050710 ccc CCC

っていうファイルがあったとして、感覚的には、

grep 20050709 hoge.txt | read STR1 STR2 STR3

みたいな感じで、
STR1 に 20050709
STR2 に bbb
STR3 に BBB

を入れたいです。

何かうまい手はないでしょうか?
よろしくお願いします。
0444名無しさん@お腹いっぱい。2005/07/09(土) 01:16:47
>>442
GNU者うざい。
0445名無しさん@お腹いっぱい。2005/07/09(土) 01:19:06
>>441
perlのワンライナーをシェルスクリプトに入れるのって
どうなんだろう

そのうちどうせなら全部perlで書いたほうが、はやいし
移植性も高いかも?
とかそんなようなことを思ったりして
0446名無しさん@お腹いっぱい。2005/07/09(土) 01:25:10
>>445
え、漏れは emacs のワンライナーをシェルスクリプトに入れているけど。。。
0447名無しさん@お腹いっぱい。2005/07/09(土) 01:28:25
やりたいことがわからない。
というか、その「感覚的には」のくだり
それそのものがやりたいわけじゃないのよね?

set -- `grep 20050709 hoge.txt` とかいう話でもないだろうし。
04484432005/07/09(土) 01:41:15
> 447
やりたいことは、
STR1 に 20050709
STR2 に bbb
STR3 に BBB を入れることです。

grep 20050709 hoge.txt | read STR1 STR2 STR3
↑で入ります?

自分の環境だと、STR1,2,3 とも空になってしまうのですが。
0449名無しさん@お腹いっぱい。2005/07/09(土) 01:44:48
ちゃんと ${STR1} で参照してるんだよね?
04504432005/07/09(土) 02:00:16
>449
はい。ソースを貼り付けられないのが悔しいのですが、
ちゃんと、${STR1} で参照しております。

普通は
grep 20050709 hoge.txt | read STR1 STR2 STR3
で、うまくいくものなのでしょうか?

ちなみに、
read STR1 STR2 STR3 < hoge.txt
だと、
STR1 に 20050708
STR2 に aaa
STR3 に AAA が入ってくれます。
0451名無しさん@お腹いっぱい。2005/07/09(土) 02:03:23
おれんとこもそれできない。
とりあえずファイル経由すれば?
0452名無しさん@お腹いっぱい。2005/07/09(土) 02:11:24
>>450
zsh だと上手くいったけど、bash はダメだった
0453名無しさん@お腹いっぱい。2005/07/09(土) 02:21:24
これは反則? ^^;;
bash-3.00$ read STR1 STR2 STR3 < <(grep 20050709 hoge.txt)
0454No Gnus is good news2005/07/09(土) 02:27:06
If I pipe the output of a command into `read variable', why doesn't
the output show up in $variable when the read command finishes?
http://www.unixguide.net/unix/bash/E4.shtml
0455名無しさん@お腹いっぱい。2005/07/09(土) 02:27:27
>>450
pipeの後に置かれたreadはsubshellで実行されるため、結果の変数は親からは見えません。
>>447のようにgrepをsubshellに回すか、
grep 20050709 hoge.txt | (read STR1 STR2 STR3; echo $STR1 $STR2 $STR3)
subshellの中で完結させるとよいでしょう。
04564432005/07/09(土) 02:44:28
皆様、アドバイスありがとうございました。
451さんの言う通り、ファイル経由にしようかと思います。

>455
なるほど、勉強になりました。
ありがとうございました。
0457名無しさん@お腹いっぱい。2005/07/09(土) 02:45:56
zsh で成功するのは zsh の拡張機能?
0458名無しさん@お腹いっぱい。2005/07/09(土) 02:56:02
むかしのreadはそもそも
read < file
もできないんじゃなかったっけか
0459名無しさん@お腹いっぱい。2005/07/09(土) 07:37:31
zsh is the shell
0460名無しさん@お腹いっぱい。2005/07/09(土) 07:48:29
grep 20050709 hoge.txt |while read STR1 STR2 STR3; do echo $STR3; done;
にしてみ。
0461名無しさん@お腹いっぱい。2005/07/09(土) 08:55:54
>>460
それ>>455と同じ。
0462名無しさん@お腹いっぱい。2005/07/09(土) 10:20:34
zshを対話的に使うなら分かるが、スクリプトに使う理由がわからん。
0463名無しさん@お腹いっぱい。2005/07/09(土) 14:05:00
よく考えてご覧なさい
0464名無しさん@お腹いっぱい。2005/07/09(土) 14:24:46
>>462
おや、思考停止ですか?
0465名無しさん@お腹いっぱい。2005/07/09(土) 15:22:40
俺もわかんない。
だってzshのスクリプトは、可搬性悪いし、保守性悪いじゃん。

可搬性悪=zshがどこにもインスコされてるわけじゃない
保守性悪=使える(よくわかってる)人の数は sh >>> zsh

これはzsh自体が悪いせいじゃない。でも上の状況を鑑みて、
shが存在するのにshを避けてzshでスクリプト書く理由わからん。
0466名無しさん@お腹いっぱい。2005/07/09(土) 15:41:11
>>465
sh スクリプトと見せかけて、bash スクリプトなんか腐るほどある。
Solaris 使ったことある?
0467名無しさん@お腹いっぱい。2005/07/09(土) 15:42:21
zshが入ってるマシンで自分用に書く場合は?なにも問題なかろう。
0468名無しさん@お腹いっぱい。2005/07/09(土) 15:45:41
>>465
俺の仕事のリーチでは十分可搬性有るし、
状況によって、使える物は何でも使う
0469名無しさん@お腹いっぱい。2005/07/09(土) 15:50:36
    ⊂_ヽ、
      .\\  /⌒\
         \ ( 冫、)  ウンチになぁれ
          > ` ⌒ヽ
         /    へ \
        /    /   \\
        レ  ノ     ヽ_つ
        /  /         ・*.・:
       /  /|          :。 *.・
       ( ( 、           ★。:’*
       |  |、 \        。・.*・; ・
       | / \ ⌒l      ;* ・。;*★ 人・
       | |   ) /      ・ ★・   (_ );; * 。・
      ノ  )   し'        ・ *   (__) * ・。・
     (_/          。*;>>465(●´ー`●)  ★.* ’★
0470名無しさん@お腹いっぱい。2005/07/09(土) 16:29:06
「可搬性」っつってんのに
「zshの入ってるPC」とか
「俺の仕事では」とか
「ウンチになぁれ」とか


バカなのかな?
0471名無しさん@お腹いっぱい。2005/07/09(土) 16:39:19
>>470
同意。

反論するなら
・zsh は可搬性が高いかどうか
・zsh は保守性が高いかどうか
にするべきだろう。

「可搬性や保守性は必要ない」っていう主張は、
「zsh は可搬性や保守性が低い」のは認めているんだよな。
0472名無しさん@お腹いっぱい。2005/07/09(土) 16:39:32
>>468
狭いリーチだな
0473名無しさん@お腹いっぱい。2005/07/09(土) 16:44:13
>>471
可搬性や保守性が高くないと使えないという前提がそもそも
おかしいという主張なんだよ

>>472
仕事柄、古くさい環境は触る必要無いんでね
■ このスレッドは過去ログ倉庫に格納されています