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

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

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


□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashなので特に注意。
FreeBSDユーザは/bin/shの正体がashなので注意。
v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。
http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/sh/
http://heirloom.sourceforge.net/sh.html
・csh/tcshのシェルスクリプトは推奨されません。
(理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
 manや参考リンクを見ましょう。
 aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)

□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。

前スレ落ちたみたいなのでリンク省略。
0065名無しさん@お腹いっぱい。2009/02/03(火) 00:12:58
echo 1 | app
0066名無しさん@お腹いっぱい。2009/02/03(火) 00:25:53
$ ttyrec x
$ app

$ exit
$ ttyplay x
0067602009/02/03(火) 02:44:31
レスありがとうございます

>>61-62
read -n 1が良さそうなのでこれを使ってみます

>>63
すみません。タイプミスですorz
正しくは「pause」です
0068名無しさん@お腹いっぱい。2009/02/03(火) 09:03:27
>>64
expect
0069名無しさん@お腹いっぱい。2009/02/03(火) 15:36:11
expect使うけどセキュリティ考えたら微妙
0070名無しさん@お腹いっぱい。2009/02/05(木) 00:30:20
bashで多重配列って使えますか?
0071名無しさん@お腹いっぱい。2009/02/05(木) 00:35:26
>>64
conquerer -bj --creeping-deth
0072名無しさん@お腹いっぱい。2009/02/05(木) 06:38:09
>>70
多次元配列という意味なら、使えない。
0073名無しさん@お腹いっぱい。2009/02/05(木) 18:40:06
速度という観点でsh、bashそれとperl、pythonを比較するとどうなんでしょう。
起動コストは抜きにして
とりあえずディレクトリーをたぐりながら正規表現での文字列探索みたいなジャンルで
好みでもかまわないので意見がききたいです。
0074名無しさん@お腹いっぱい。2009/02/05(木) 18:52:19
>>73
実際にやってみればいいじゃん。
まあシェルスクリプトは速度を求めるものじゃないけどね。
0075名無しさん@お腹いっぱい。2009/02/05(木) 18:53:41
>>73
速い順に、
sh > perl > bash > python
で、大体合ってる
0076名無しさん@お腹いっぱい。2009/02/05(木) 19:03:08
sh, bashは他のプログラムをfork, execしなきゃならないから
perl, python > sh, bash だろ。JK
0077名無しさん@お腹いっぱい。2009/02/05(木) 20:23:44
シェルにもなって正規表現爆速のTcl最強って話ですね、わかります
0078名無しさん@お腹いっぱい。2009/02/06(金) 12:09:09
Command-line Fu < The best UNIX commands on the web
http://www.commandlinefu.com/commands/browse
0079名無しさん@お腹いっぱい。2009/02/06(金) 12:18:34
-Fuってどういう由来の語なんだろうね
0080名無しさん@お腹いっぱい。2009/02/06(金) 12:19:50
符じゃないか?

護符とかの。
0081名無しさん@お腹いっぱい。2009/02/06(金) 12:51:06
http://ja.wikipedia.org/wiki/GIMP
なお、Script-Fuの名はカンフー(Kung-fu)からきている。
0082名無しさん@お腹いっぱい。2009/02/06(金) 15:28:51
夫は男らしいさまを表す字です。
偉丈夫、気丈夫、大丈夫
0083名無しさん@お腹いっぱい。2009/02/06(金) 15:34:19
PC的にアレかもね
0084名無しさん@お腹いっぱい。2009/02/06(金) 15:57:59
例えばfindやgrepをshが呼び出す場合別プロセスで使っていたら
起動コスト安くなりませんか?めんどいけど
Tclってきるつもりだったけれどある程度の機能がセットになっているのならば
選択肢なのかなぁ。
でも要するにざっくりとみたら対さないんだったら素直にperl使うのが楽なんですかね、
0085名無しさん@お腹いっぱい。2009/02/06(金) 16:11:31
tcl, perl
いつの人ですか?
ここ3年くらい使ったことないよ!
0086名無しさん@お腹いっぱい。2009/02/06(金) 17:36:19
tcl なんぞより Bourne Shell の方がよっぽど古いぞと問い詰めたい
0087名無しさん@お腹いっぱい。2009/02/06(金) 23:17:30
echo < hoge
これってhogeの内容がechoに渡されると思うんだけど、
なんで何も表示されないんですか?
0088名無しさん@お腹いっぱい。2009/02/06(金) 23:30:30
echoはコマンド引数を表示するように作られていて、標準入力は読まないからです。
0089名無しさん@お腹いっぱい。2009/02/06(金) 23:45:25
>>88
了解しました

[ana@coppola ~]$ echo <(ls)
/proc/self/fd/63

ではこうなるのはいったいなぜですか?
というか、
/proc/self/fd/63
って?
0090名無しさん@お腹いっぱい。2009/02/07(土) 00:16:57
/dev/fd/#は#に対応するファイルディスクリプタに名前が付いたものと思えばいいです。
<(command)はprocess substitutionというbashの特殊な記法でファイルディスクリプタ
ファイル(/dev/fd/#)名に置換されます。
0091名無しさん@お腹いっぱい。2009/02/07(土) 00:43:49
初期のシェルにもその記法はあったが、
曖昧さがあるので|記法に変った。
0092ミジンコ未満2009/02/07(土) 01:17:25
bashのスクリプトでDVD/CDドライブにメディアが挿入されている場合に
コマンドを実行する。なんてことをするにはどうすればいいですか
0093名無しさん@お腹いっぱい。2009/02/07(土) 01:32:22
Linuxならここの/procで。
http://www.linux.or.jp/JF/JFdocs/SCSI-2.4-HOWTO/sr.html
0094名無しさん@お腹いっぱい。2009/02/07(土) 11:06:58
>>92

head -c 1 /dev/cdrom > /dev/null 2>&1 && command


>>93
そのリンク見ても、メディアが挿入されてるかどうかの判定はできないよ。
0095名無しさん@お腹いっぱい。2009/02/08(日) 00:47:14
あるフォルダに複数のファイルが入っていて、その中から
暗号化zipを別のフォルダに分けるっていう事、どうやればいいでしょうか
0096名無しさん@お腹いっぱい。2009/02/08(日) 00:49:33
お前、その質問を他人から受けてやりたい事が解るのか?
0097922009/02/08(日) 01:19:09
>>93-94
ありがと
なんとかなりそうです
0098名無しさん@お腹いっぱい。2009/02/08(日) 02:15:27
2つのディレクトリ内のファイルの更新日時を比較するにはみなさんどうしていますか?
現状では、2つのディレクトリ内のファイルは同期が取れていますが、たまに異なる更新日時のファイルが出来ます。
その同期の取れていないファイルはできれば抜き出したいです。
ファイルは全部で5000件くらいあります。

1.ls -ltでディレクトリ内一覧情報を出してファイルに出力
2.出したファイルから不要な情報を削除(ユーザー名とか)して時間とファイル名だけにしぼる
3.上の1と2を両ディレクトリで行う
4.diffでファイル同士比較
5.偏った情報を出力

これをシェルでやらせようと思ってますが、どうも効率を悪い気がします。
0099名無しさん@お腹いっぱい。2009/02/08(日) 03:18:26
結局何をしたいのか
ところどころ日本語も意味不明

更新日時の比較なら、ls -lt の結果を比較すればいいし
ファイル内容の比較をしたいのなら、diff や dircmp で
ディレクトリを指定すればいい
0100982009/02/08(日) 04:46:20
>>99
ありがとうございます。
おとなしく更新日時を取ってきてdiffで比較します。
0101名無しさん@お腹いっぱい。2009/02/08(日) 07:23:22
>>98
なぜ同期ツールを始めから使わないのか?
e.g. rsync等
0102名無しさん@お腹いっぱい。2009/02/08(日) 16:13:21
readlinkコマンドがないOSで、
readlink相当のことをシェルでやるには、
どうやるのが定番ですか?

シンボリックリンクの中にはスペースや特殊記号等、
すべてアリの状態でお願いします。
0103名無しさん@お腹いっぱい。2009/02/08(日) 16:17:18
シェルってゆうな。クズ。
0104名無しさん@お腹いっぱい。2009/02/08(日) 16:26:43
ls -l で行末を読むとか
0105名無しさん@お腹いっぱい。2009/02/08(日) 16:57:46
>>104
> シンボリックリンクの中にはスペースや特殊記号等、
> すべてアリの状態でお願いします。
0106名無しさん@お腹いっぱい。2009/02/08(日) 17:05:41
>>104

$ ln -s 'hoge -> hage' 'boke -> kasu'
$ ls -l
lrwxrwxrwx 1 guest guest 12 Feb 8 17:05 boke -> kasu -> hoge -> hage

こういう状態で、どうやって判定するのかね?
0107名無しさん@お腹いっぱい。2009/02/08(日) 18:26:11
>>102
perl -e "print readlink ファイル名;"
でどう?
perl はたいてい入ってるし
0108名無しさん@お腹いっぱい。2009/02/08(日) 22:41:27
>>104
lrwxrwxrwx
一文字目の l はどういう意味?
0109名無しさん@お腹いっぱい。2009/02/08(日) 22:45:41
>>108
お前、>>105 が言わんとしてることをわかってない

boke -> kasu -> hoge -> hage

この部分を見て、どこがシンボリックリンクの中身か判読できないだろw
0110名無しさん@お腹いっぱい。2009/02/08(日) 22:50:11
>>108
>>106 を良く読め、

ls -lの結果が、 boke -> kasu -> hoge -> hage となった場合、

「hage」を指している 「boke -> kasu -> hoge」と言うsymlinkかも知れないし、
「hoge -> hage」と言うファイルを指している 「boke -> kasu」と言うsymlinkかも知れないし、
「kasu -> hoge -> hage」と言うファイルを指している 「boke」と言うsymlinkかも知れない、
ということだな。
0111名無しさん@お腹いっぱい。2009/02/08(日) 23:26:17
わかってない奴が湧いてるな
0112名無しさん@お腹いっぱい。2009/02/09(月) 00:30:15
#!/bin/sh
(
echo a
echo b
)

これと

#!/bin/sh
{
echo a
echo b
}

これってなんか違いあります?
0113名無しさん@お腹いっぱい。2009/02/09(月) 04:42:06
プロセスを起動するかどうか
0114名無しさん@お腹いっぱい。2009/02/09(月) 06:32:24
>>113
実際にはシェル内部で最適化されるから、
( ) を使ってもプロセスは起動されない。

>>112
これだけだと違いは起きない。
( ) や { } 以外の他の部分の記述によっては違いが出ることもあるというだけ。
0115名無しさん@お腹いっぱい。2009/02/09(月) 23:28:32
>>106
ls -l と ls -lF の結果を比較すればできそうだから、あとはまかせた。
0116名無しさん@お腹いっぱい。2009/02/10(火) 04:06:30
readlink(1)ってのもあるよ。
0117名無しさん@お腹いっぱい。2009/02/10(火) 06:44:56
>>116
>>102
「readlinkコマンドがないOSで、」

最近、質問をちゃんと読まない人多いね
0118名無しさん@お腹いっぱい。2009/02/10(火) 09:48:36
ほんと、問題を良く読まないのが沢山いるな。
>>102はreadlink相当のことをビルトインコマンドとして持っているシェルを
探しているんだぞ。

>>102
> readlink相当のことをシェルでやるには、
0119名無しさん@お腹いっぱい。2009/02/10(火) 09:58:01
readlink がなければ stat -f %Y を使えばいいじゃない
0120名無しさん@お腹いっぱい。2009/02/10(火) 10:00:52
>>119
readlinkがないOSにはstatもないと考えるのが妥当。

あと、stat -f というオプションはFreeBSD方言だから気を付けろ。
0121名無しさん@お腹いっぱい。2009/02/10(火) 11:04:50
stat --printfの"%N"はシェルスクリプトで使いづらいよな。

$ stat --printf "%n\n" /vmlinuz
/vmlinuz
$ stat --printf "%N\n" /vmlinuz
`/vmlinuz' -> `boot/vmlinuz-2.6.27-11-generic'

->とかquoteとかいらねーよ
0122名無しさん@お腹いっぱい。2009/02/10(火) 13:20:19
>>120
マリー アントワネットにマジレスする不粋
0123名無しさん@お腹いっぱい。2009/02/10(火) 15:07:27
>>122
おれには>>119 がマジで stat -f %Y が他のOSでも使えると思い込んでるように見えるが、
0124名無しさん@お腹いっぱい。2009/02/10(火) 15:15:42
ビルトインコマンドとしてstat -fを持ってるシェルはどれだ?
0125名無しさん@お腹いっぱい。2009/02/10(火) 15:46:31
>>123
しゅぎょーが足らないな
0126名無しさん@お腹いっぱい。2009/02/10(火) 16:08:23
>>125
言い訳見苦しい。本当に知らなかったんだねw
0127名無しさん@お腹いっぱい。2009/02/10(火) 16:12:10
readlink って、ファイル名がわかっているときしか使えないんだろ。
ファイル名がわかってるなら、ls -l を解析できるんじゃないか?

lrwxrwxrwx 1 guest guest 12 Feb 8 17:05 boke -> kasu -> hoge -> hage
ファイル名が boke ならば 'kasu -> hoge -> hage'
ファイル名が 'boke -> kasu' ならば、 'hoge -> hage'
が取り出せればいいんじゃないの?

0128名無しさん@お腹いっぱい。2009/02/10(火) 21:01:33
シェルはリロードには対応してないんでしょうか?
たとえば、lsって打ちますよね、
で、hoge1 hoge2 とか表示されます。
そのあと、rm hoge1 ってやっても、
上の ls のところのシェルには hoge1 が表示されたままになります。
もう一回 ls を売っても、下の画面に2重に出てきて、
上のシェルの ls が更新されません
0129名無しさん@お腹いっぱい。2009/02/10(火) 21:17:20
ひねりが足りない要努力
0130名無しさん@お腹いっぱい。2009/02/10(火) 21:18:01
シェルに表示されたままという意味がよくわかりませんが、
端末の画面上ということですね。

CUIの端末の元祖はテレタイプです。
これはキーボードとプリンタがくっついたものです。
プリンタで打ち出されたlsの結果がいつのまにか変化するようなことはありません。
画面に表示するようになった現在でも同じです。
0131名無しさん@お腹いっぱい。2009/02/10(火) 21:30:20
>>130
プリンターは繋いでいません。
プリーンターを繋げばリロードが治るんでしょうか?
良くわかりませんが??
0132名無しさん@お腹いっぱい。2009/02/10(火) 21:37:26
ttp://homepage1.nifty.com/plusworld/TTY/TTYALL.GIF
こういうのを購入して接続するとリロードが治るはずです。
どこで売ってるかは知らないので、がんばって探してください。
なければあきらめましょう。
0133名無しさん@お腹いっぱい。2009/02/11(水) 00:05:14
ダイヤルなつかしい
0134名無しさん@お腹いっぱい。2009/02/11(水) 09:36:33
>>102

#!/bin/sh

echo 'b[9];main(int c,char**v){printf("%.*s?n",readlink(v[1],b,36),b);}'|gcc -xc - 2>/dev/null;./a.out "$1";rm a.out
0135名無しさん@お腹いっぱい。2009/02/11(水) 09:37:18
あはははははは
0136名無しさん@お腹いっぱい。2009/02/11(水) 10:46:40
>>134
ソースにじかに "$1" を入れ込めばもっと短くなるだろ

echo 'b[9];main(){printf("%.*s\n",readlink("'"$1"'",b,36),b);}'|gcc -xc - 2>/dev/null;./a.out;rm a.out
0137名無しさん@お腹いっぱい。2009/02/11(水) 13:06:27
>>136
> 2>/dev/null

書き込めないcurrent directoryで、

/usr/bin/ld: cannot open output file a.out: Permission denied

すら見られませんが…
0138名無しさん@お腹いっぱい。2009/02/12(木) 16:45:07
#!/usr/bin/tcc -run
b[9];main(int c,char**v){printf("%.*s\n",readlink(v[1],b,36),b);}
0139名無しさん@お腹いっぱい。2009/02/14(土) 18:30:52
cpu使用率を出力するコマンドが欲しいんですがtopの出力を加工する感じになりますか?
0140名無しさん@お腹いっぱい。2009/02/14(土) 18:32:02
>>139
uptime
0141名無しさん@お腹いっぱい。2009/02/15(日) 01:04:50
vmstatとかじゃだめ?
0142名無しさん@お腹いっぱい。2009/02/15(日) 02:12:42
>>139
/proc/statのcpu行の最初の三つがCPUタイム
0143名無しさん@お腹いっぱい。2009/02/15(日) 09:42:44
ハードリンク先を求めるのに、findで探す以外に効率的なシェルって作れないんですか?
0144名無しさん@お腹いっぱい。2009/02/15(日) 09:44:20
シェルってゆうな。クズ。
0145名無しさん@お腹いっぱい。2009/02/15(日) 09:56:36
To find the hard links, is there some way to make an efficient shell without find ?
0146名無しさん@お腹いっぱい。2009/02/15(日) 10:30:18
ファイルから全文を読み込んで、別ファイルに(追記で)書き込むにはどんな記述を
すればいいですか?
phpで言えば
$hen01 = $_POST["読み込んだ文字"];
$fp = fopen('書き込み先.txt', 'a+');
flock($fp, LOCK_EX);
$return = fputs($fp,"$hen01\n");
flock($fp, LOCK_UN);
fclose($fp);
こんな感じで一旦あるテキストファイルの文字列を全部読み込んで、別のファイルに
追記書き込みの処理をしたいんです。

0147名無しさん@お腹いっぱい。2009/02/15(日) 10:40:05
cat aaa >> bbb
0148名無しさん@お腹いっぱい。2009/02/15(日) 10:47:30
>>147

なるほどcatを使うんですね、即レスありがとうございました。
0149名無しさん@お腹いっぱい。2009/02/15(日) 11:00:11
">>"がキモだとわかっているのだろうか。
0150名無しさん@お腹いっぱい。2009/02/15(日) 11:12:06
ふむ、慣れない内はシェルに>の動作を制限させとった方がいいかも?
でも制限させたらさせたで面倒なんだよな。
仕事で使うんならいざしらず、遊びで使うんなら
少々飛ばそうが関係ないし。
0151名無しさん@お腹いっぱい。2009/02/15(日) 11:18:56
シェルの話はスレ違い
0152名無しさん@お腹いっぱい。2009/02/15(日) 11:23:28
>>147
それだと、>>146 のphpでやってる flock の処理が出来てないと思うが。
同時にプロセス起動されたら出力がぐちゃぐちゃに混ざる。
0153名無しさん@お腹いっぱい。2009/02/15(日) 11:30:38
phpは知らんが146はロックできなかった場合の処理をしてないようなので
147でいいんじゃないの?
0154名無しさん@お腹いっぱい。2009/02/15(日) 11:35:22
>>153
ロックできなかった場合はflockのところでロック解除になるまで待たされる。
だから、ロックの処理はちゃんと行なわれている。

よって >>147 ではダメ。
0155名無しさん@お腹いっぱい。2009/02/15(日) 11:43:02
>>153
>phpは知らんが

知らないのに突っ込むと恥をかくという典型例ですな
0156名無しさん@お腹いっぱい。2009/02/15(日) 11:50:00
そもそも >>146 の文章とコード例がずれてるのが原因のような
0157名無しさん@お腹いっぱい。2009/02/15(日) 12:01:31
lockf bbb sh -c "cat aaa >>bbb"

lockf(1)が無かったら作れ。
0158名無しさん@お腹いっぱい。2009/02/15(日) 12:04:49
>>146
flock(1)が存在するOS (Linux)なら、

flock out.txt cat in.txt >> out.txt
0159名無しさん@お腹いっぱい。2009/02/15(日) 12:18:35
凄く細かいことを言うと、
>>157のスタイルの方が>>158のスタイルより、
ファイルロック以前に書き込まれる恐れがない。
0160名無しさん@お腹いっぱい。2009/02/15(日) 12:21:59
おれも、それを指摘しようと思ったがアペンドだから問題ないので止めた。
>>158が知っていたのかはわからない。
0161名無しさん@お腹いっぱい。2009/02/15(日) 12:26:13
158 だが、知ってた上で無駄な sh -c を外したんだよ。
0162名無しさん@お腹いっぱい。2009/02/15(日) 12:28:31
無駄ではなく、過剰仕様というのなら分かるが…
0163名無しさん@お腹いっぱい。2009/02/15(日) 12:32:41
>>162
いや、仕様とか品質とか関係なく無駄。

アペンドで先にオープンされるだけであって、
実際の書き込みはロック取得後に行なわれるから、
sh -c なしで全く問題ない。
0164名無しさん@お腹いっぱい。2009/02/15(日) 12:35:16
>>157
それだと、実行後に bbbが削除されるだろ(笑)

>>158
こっちは合格。
■ このスレッドは過去ログ倉庫に格納されています