トップページ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 でトレースしましょう。

前スレ落ちたみたいなのでリンク省略。
0015名無しさん@お腹いっぱい。2009/01/29(木) 18:49:36
引数も渡すならこんな感じ
#!/bin/sh
busybox free $*
0016名無しさん@お腹いっぱい。2009/01/29(木) 18:52:52
>>14
えっと、何か勘違いされてますか?
シェル名はなんでもいいんですが、bosyboxとして

$ cat bosybox
#!/bin/sh
この行をお願いします
この行をお願いします
この行をお願いします
:


$ ./bosybox
…実行結果…


ということですが、、
0017名無しさん@お腹いっぱい。2009/01/29(木) 19:01:29
vmstatあたりを sed awkして船山に登れば医院じゃないの?
0018名無しさん@お腹いっぱい。2009/01/29(木) 19:08:49

なないかかんちがいてまちぇんでちゅか?
0019名無しさん@お腹いっぱい。2009/01/29(木) 19:08:49
>>16
$ cat busybox
#!/bin/sh
/bin/busybox $*

$./busybox free
...
0020名無しさん@お腹いっぱい。2009/01/29(木) 19:16:00
>>19
/bin/busybox というのはbash依存、またはOS依存だと思います。
どのOSにもあるコマンドだけを組み合わせてfree相当のシェルを作って下さい。
0021名無しさん@お腹いっぱい。2009/01/29(木) 19:17:55
>>20
busyboxはbash依存でもなければOS依存でもありません。
freeが組み込まれたシェルです。
0022名無しさん@お腹いっぱい。2009/01/29(木) 19:21:59
>>15
busybox内部の freeコマンドは、引数に対応してない。
あと、引数を渡すにしても $* で渡してはいけない。
(シェルスクリプトのコーディングルールとして)

よって失格。
0023名無しさん@お腹いっぱい。2009/01/29(木) 19:24:23
>>22
そうなのか。フォローthx
0024名無しさん@お腹いっぱい。2009/01/29(木) 19:25:16
>>20
無理
0025名無しさん@お腹いっぱい。2009/01/30(金) 07:27:08
diffコマンドで2つのテキストファイルの中身を比較して、
一緒だったら次のAというコマンドを、違ったらBというコマンドを実行するには
どう書いたらいいですか?
0026名無しさん@お腹いっぱい。2009/01/30(金) 07:35:41
>>25

if diff hoge.txt boke.txt > /dev/null
then
commandA
else
commandB
fi
0027名無しさん@お腹いっぱい。2009/01/30(金) 07:42:04
完全一致でいいなら、diff >/dev/null よりも、cmp -s
0028名無しさん@お腹いっぱい。2009/01/30(金) 07:45:05
>>27
>>25 「diffコマンドで」
0029名無しさん@お腹いっぱい。2009/01/30(金) 07:50:34
>>26
diff文が使えるようなシェルってあるんですか?

うちのシェルはif文は if [ ... ] みたいに書く普通のシェルです。
普通のシェルでお願いします。
0030名無しさん@お腹いっぱい。2009/01/30(金) 07:53:55
20/100点
0031名無しさん@お腹いっぱい。2009/01/30(金) 07:58:05
if [ `diff a.txt b.txt | wc -c` == 0 ]; then
comA
else
comB
fi

だろ?
0032名無しさん@お腹いっぱい。2009/01/30(金) 10:12:43
つまらんスレだな、ここは
0033名無しさん@お腹いっぱい。2009/01/30(金) 10:58:24
>>29
その [ ... ] が何を示すのか勉強しなおしてこい
0034名無しさん@お腹いっぱい。2009/01/30(金) 16:59:25
>>33
条件文を表してるのは知ってますよ
0035名無しさん@お腹いっぱい。2009/01/30(金) 19:21:23
[ もdiffもコマンドってことじゃないかな
[ ... ]っつー見かけに惑わされちゃいかん
0036名無しさん@お腹いっぱい。2009/01/30(金) 22:19:18
% where '['
[: shell built-in command
/bin/[
0037名無しさん@お腹いっぱい。2009/01/30(金) 22:32:56
質問です。
2つのコマンド、commandA と commandB の標準出力同士を、
テンポラリファイルを作らずに diffコマンドで比較したい時、
bashなら、

diff <(commandA) <(commandB)

でできますが、
これを標準シェルでやるにはどうすればいいですか?
0038名無しさん@お腹いっぱい。2009/01/30(金) 22:41:36
>>37
commandA | (commandB | diff /dev/fd/3 -) 3<&0
0039名無しさん@お腹いっぱい。2009/01/30(金) 22:42:34
>>37
無理。
bash使うか、一旦ファイルに落せ。
0040名無しさん@お腹いっぱい。2009/01/30(金) 22:47:41
答が出たあとで、無理とか言ってる奴ってなんなの?
0041名無しさん@お腹いっぱい。2009/01/30(金) 22:57:08
>>38
おおでけた。THX!
0042名無しさん@お腹いっぱい。2009/01/30(金) 23:32:55
>>34
その昔は、 /bin/[ なんてのが有ったんだがなぁ。
0043名無しさん@お腹いっぱい。2009/01/30(金) 23:34:28
>>42
今でもあるだろ

0044名無しさん@お腹いっぱい。2009/01/30(金) 23:38:21
>>42
今でもあるだろw

$ which '['
/usr/bin/[
0045名無しさん@お腹いっぱい。2009/01/30(金) 23:50:58
Bシェルなのに which使う奴ってなんなの?
0046名無しさん@お腹いっぱい。2009/01/30(金) 23:52:10
>>45
すまん、BSD育ちなんだw
0047名無しさん@お腹いっぱい。2009/01/30(金) 23:59:24
昔はshにtypeなんてなく、whichは外部コマンドだった。
cshはaliasとかがあるせいでwhichを内部コマンドに持った。
0048名無しさん@お腹いっぱい。2009/01/31(土) 07:29:55
>>38
/dev/fd/3 って純正シェルでも使えるの??
0049名無しさん@お腹いっぱい。2009/01/31(土) 13:15:29
シェルじゃなくてOSだろ?
0050名無しさん@お腹いっぱい。2009/01/31(土) 13:41:51
>>49
なんでもいいから、結局使えるの??
0051名無しさん@お腹いっぱい。2009/01/31(土) 13:58:32
レスしたら負けだ。
0052名無しさん@お腹いっぱい。2009/01/31(土) 19:54:54
これは釣りですよね?
いくらなんでもそんな質問しないもんね?
0053名無しさん@お腹いっぱい。2009/01/31(土) 20:15:42
一般論として、/dev以下のファイルはシェルによって特別扱いされることが
あり得る。

例えば、bashだと、/dev/stdout とかは、実際の /dev/stdoutを読まずに
シェルが /dev/stdoutという文字列を特別扱いして動作する。

そのことを考慮すれば、/dev/fd/n がシェルに依存しているかも知れないと
考えることにも一定の合理性が認められる。
0054名無しさん@お腹いっぱい。2009/01/31(土) 20:59:54
無いからもう寝ろ
0055名無しさん@お腹いっぱい。2009/02/01(日) 00:46:46
こうしてスレに平和が戻った。。。end
0056名無しさん@お腹いっぱい。2009/02/01(日) 02:18:13
[ を条件文だと言ったり、/dev/fd/3 がシェルに依存していると言ったり、
面白い人が増えたなw
0057名無しさん@お腹いっぱい。2009/02/01(日) 08:04:35
>>56
/dev/fd/3 がシェルに依存してるのは本当だよ。
0058名無しさん@お腹いっぱい。2009/02/01(日) 08:23:14
>>56

man bash | less -p /dev/fd/fd

man zshmisc | less -p /dev/fd/n

if file is of the form `/dev/fd/n',
where n is an integer, then the test applied to the open file whose
descriptor number is n, even if the underlying system does not support
the /dev/fd directory.


> even if the underlying system does not support the /dev/fd directory
> even if the underlying system does not support the /dev/fd directory
> even if the underlying system does not support the /dev/fd directory
> even if the underlying system does not support the /dev/fd directory
0059名無しさん@お腹いっぱい。2009/02/01(日) 22:53:38
日本語でおk
0060名無しさん@お腹いっぱい。2009/02/02(月) 04:47:50
bash(Fedora10)のシェルスクリプトでMS-DOSのバッチファイルのpuaseみたいな動作を
させるにはどのようにしたらいいですか?
0061名無しさん@お腹いっぱい。2009/02/02(月) 06:25:59
>>60
read
0062名無しさん@お腹いっぱい。2009/02/02(月) 10:24:22
>>60
bashの場合は read -n 1 の方がよりpauseの動作に近いかと
0063名無しさん@お腹いっぱい。2009/02/02(月) 22:25:23
>>61-62
質問欲嫁。それはpauseの動作。>>60 の質問はpuaseの動作。
0064名無しさん@お腹いっぱい。2009/02/03(火) 00:09:20
アプリケーションを実行した時に入力を求められるような場合
どう処理すればよいのでしょうか?
応答に対して入力する値(番号など)決まっているという前提でお願いします
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
これだけだと違いは起きない。
( ) や { } 以外の他の部分の記述によっては違いが出ることもあるというだけ。
■ このスレッドは過去ログ倉庫に格納されています