トップページunix
987コメント278KB

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

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2012/11/15(木) 18:57:33.11
シェルスクリプトの総合スレです。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashまたはdashなので特に注意。
 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でそれらしい単語による簡単な検索もできます。
・シェルで使えるワイルドカード等は正規表現ではありません。
 正規表現の話題はスレ違い(正規表現スレへ)
・シェルスクリプトのことをシェルってゆーな
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 awkまたはperlの方が適した処理にはそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
□回答者への注意事項:
・シェルスクリプトでの処理方法を質問しているのに、よくわからずに
 「そういうのはperl使いましょう」と回答するのはやめましょう。
 安易にperlに逃げずにシェルスクリプトで処理するのが頭のいいやり方。
前スレ
シェルスクリプト総合 その20
http://toro.2ch.net/test/read.cgi/unix/1339083351/
0109名無しさん@お腹いっぱい。2013/01/12(土) 21:11:02.86
2> /dev/null

2>&-
って書くとまずいことあるの?

おしえて先生!
0110名無しさん@お腹いっぱい。2013/01/12(土) 22:41:52.39
>>106
ほとんど手が入っていないであろう net2 のソース持ってくるってのは?
0111名無しさん@お腹いっぱい。2013/01/13(日) 14:15:52.18
>>109
writeの失敗を検出するようなコードが書いてあると困る
0112名無しさん@お腹いっぱい。2013/01/13(日) 14:36:10.22
どこにですか?
0113名無しさん@お腹いっぱい。2013/01/13(日) 15:03:28.37
#include <unistd.h>
int main(){
if(write(2,"hello",5) == -1){
return 1;
}
return 0;
}
こんな感じかな。
0114名無しさん@お腹いっぱい。2013/01/19(土) 01:07:47.55
>>109 &amp;- ってどういう構文なの? htmlとか?
>>111 エラーを返さない方が困ります
0115名無しさん@お腹いっぱい。2013/01/19(土) 02:20:17.72
仕様変更した2chと、
それに対応してない専ブラ使うやつと、
&amp;が何かも知らずにつっこむやつ
0116名無しさん@お腹いっぱい。2013/01/19(土) 02:32:56.96
と、ドヤ顔で解説する奴と

ニヤニヤしながら傍観してるオレ。
0117名無しさん@お腹いっぱい。2013/01/19(土) 10:36:37.19
あー &ー なのか
失礼
0118名無しさん@お腹いっぱい。2013/01/19(土) 18:28:47.20
初心者だから使えるコマンドがlsとかなのは共通事項。
たまにネットがおかしいと聞くと言われて打った
ifconfigは command not found になったりするんだよね。
0119名無しさん@お腹いっぱい。2013/01/19(土) 18:39:44.08
ifconfigは/usr/sbinにあったりするからな。
0120名無しさん@お腹いっぱい。2013/01/19(土) 18:50:09.03
解決策を聞いてるんじゃないよ。(というか知ってるし)
そうそうと共感してくれればいいのに。
面倒臭い人ね。
0121名無しさん@お腹いっぱい。2013/01/19(土) 21:26:02.44
そういう大事なコマンドは/sbinだろ。
0122名無しさん@お腹いっぱい。2013/01/20(日) 00:53:25.44
どこにシェルスクリプト要素があるんだ?
0123名無しさん@お腹いっぱい。2013/01/20(日) 02:42:53.88
>>120
誰でも知ってるような事を書いて
共感しろとは、勘違いも甚だしい
0124名無しさん@お腹いっぱい。2013/01/20(日) 03:42:08.87
さすがに生まれたての赤ん坊は知らねぇだろ
0125名無しさん@お腹いっぱい。2013/01/20(日) 05:26:07.60
赤ん坊が無知を装うのは大昔からの通例だろ
0126名無しさん@お腹いっぱい。2013/01/20(日) 05:38:37.73
会話できない以上知ってるかどうか確認する手段がないからな。
0127名無しさん@お腹いっぱい。2013/01/20(日) 10:43:48.19
くだらない質問ですが、
次のシェルスクリプトで★マークに入る方法があれば教えてください。
ARG0="$0"
while [ -h "$ARG0" ]; do
ls=`ls -ld "$ARG0"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
  ★
ARG0="$link"
else
ARG0="`dirname $ARG0`/$link"
fi
done

処理時代はシンボリックリンクの実体を辿る処理だという事は調べて、
なんとか分かったんですが、★の処理にはいる条件がどうしても分かりません。
別に入らなくてもいいのですが、気になってしまって・・・
0128名無しさん@お腹いっぱい。2013/01/20(日) 10:50:31.37
絶対パスへのリンク、じゃないの?
0129名無しさん@お腹いっぱい。2013/01/20(日) 10:54:20.46
>>127
解答を聞いてるんじゃないよ。
そうそう、こういう構文だと条件がわかりにくいよねぇー、
って共感してくれればいいんだけど。
0130名無しさん@お腹いっぱい。2013/01/20(日) 11:06:43.97
ってかreadlinkを自分で分かりにくく書いてみたってことでいいの?
01311272013/01/20(日) 11:12:54.89
>>128
ありがとうございます。
絶対パスで調べて、リンクを作りなおしたら通りました。
01321272013/01/20(日) 11:25:51.23
>>130
Linuxを使い始めたばかりで、
とりあえず適当なソフトをWebを見ながらインストールしていました。
その中でTomcatというソフトをインストールするのに、
シェルスクリプトの設置が必要と書かれており、そのサンプルが記載されていました。
しかし、サンプルの意味が全く分からなくて、そのまま使っていいのかも分からず
一から調べている最中でした。
0133名無しさん@お腹いっぱい。2013/01/20(日) 13:47:00.29
>>130
http://svn.apache.org/repos/asf/commons/proper/daemon/tags/COMMONS_DAEMON_1_0_7/src/samples/Tomcat7.sh
の事だな。特定の環境にしか存在しないreadlinkは使いたくなかったんだろ。
素人は黙ってなよ。
0134名無しさん@お腹いっぱい。2013/01/20(日) 14:49:14.74
リテラシ高いな
感心感心
0135名無しさん@お腹いっぱい2013/01/23(水) 14:41:17.73
もし、Aのディレクト内が空だったら、○○しなさい

の一番簡単なスクリプトは?
0136名無しさん@お腹いっぱい。2013/01/23(水) 14:56:34.29
find A -empty | fgrep -x A >/dev/null && ○○
0137名無しさん@お腹いっぱい。2013/01/23(水) 15:51:12.07
解答を聞いてるんじゃないよ。
そうそう、ディレクトリが空かどうかの判断って簡単にできないよねぇー
って共感してくれればいいんだけど。
0138名無しさん@お腹いっぱい。2013/01/23(水) 16:51:23.23
簡単にできるけど、回答知りたくないらしいから黙っておこう。
0139名無しさん@お腹いっぱい。2013/01/23(水) 17:03:26.94
コピペやん
0140名無しさん@お腹いっぱい。2013/01/23(水) 19:43:01.34
>>137
さぁ、お前のハードリンクを数えろ
0141名無しさん@お腹いっぱい。2013/01/23(水) 20:37:43.99
それだと内部のディレクトリ数しかわかんねえよ
0142名無しさん@お腹いっぱい。2013/01/23(水) 21:01:24.46
141が何を主張しているのかエスパーお願い
0143名無しさん@お腹いっぱい。2013/01/23(水) 21:27:00.12
エスパーしよう。
>>141 は、ディレクトリのハードリンク数が2かどうかで空ディレクトリを判断しても、
それは「サブディレクトリ数+2」の値でしかないから、
内部のディレクトリ数が0で通常ファイルだけ存在する場合まで
空ディレクトリと誤判定してしまう、と主張しているようだ。

要するに、空ディレクトリ≠葉(leaf)ディレクトリ
0144名無しさん@お腹いっぱい。2013/01/23(水) 21:31:31.38
.と..が必ず存在するから、空ディレクトは存在しない。
ゆえに判定式は定数式。
0145名無しさん@お腹いっぱい。2013/01/23(水) 21:56:03.02
エスパーってほどじゃないだろ
0146名無しさん@お腹いっぱい。2013/01/23(水) 23:08:40.40
>>137
消してみればいいんだしね。
0147名無しさん@お腹いっぱい。2013/01/23(水) 23:09:52.41
権限がなかったり
0148名無しさん@お腹いっぱい。2013/01/24(木) 01:17:26.13
>>137
共感できない。
0149名無しさん@お腹いっぱい。2013/01/24(木) 05:53:53.02
教官!できない…
0150名無しさん@お腹いっぱい。2013/01/24(木) 08:38:20.39
ようするに >>141 は . と .. がリンク数に含まれることを知らないってことかな
0151名無しさん@お腹いっぱい。2013/01/24(木) 08:43:24.58
>>150
すでに>>143が解説済み。
0152名無しさん@お腹いっぱい。2013/01/24(木) 09:15:47.01
空ディレクトリが存在しないのであれば
rmdirはどのディレクトリも削除できないのでは?
0153名無しさん@お腹いっぱい。2013/01/24(木) 09:35:00.86
こまけぇことは気にしないで消せばいいんだよ
0154名無しさん@お腹いっぱい。2013/01/24(木) 11:20:22.52
>>152
空ディレクトリは.と..以外のファイル/ディレクトリが無いディレクトリのこと
0155名無しさん@お腹いっぱい。2013/01/24(木) 18:41:29.19
/a.appを起動
プロセスを終了

を5秒ごとに繰り返すコマンド書いてくださいな
0156名無しさん@お腹いっぱい。2013/01/24(木) 18:47:02.12
なんでそんな傲慢なの?
0157名無しさん@お腹いっぱい。2013/01/24(木) 18:51:36.35
そうそう、アプリを起動してプロセスを終了を、
5秒ごとに繰り返したりしたいこと多いよね、共感します。
0158名無しさん@お腹いっぱい。2013/01/24(木) 21:04:28.31
>>155
プロセスを終了 って、どのプロセスでもいい?
0159名無しさん@お腹いっぱい。2013/01/24(木) 21:33:59.04
>>155
while sleep 5;do pkill a.app;/a.app &;done

ほんとはpid拾うべきか。$?だっけ。
0160名無しさん@お腹いっぱい。2013/01/25(金) 01:43:15.60
$! な
0161名無しさん@お腹いっぱい。2013/01/25(金) 11:02:15.89
.appって拡張子はMac OS Xのbundleか?
だとするとopen -a /a.appだろうけど、まあapplescriptで書いた方がいいよ。
ジェントルに終了させられるし。
0162名無しさん@お腹いっぱい。2013/01/25(金) 11:31:59.01
applescriptって#がコメントにならないから
#!/usr/bin/osascriptって書けないんだよね…。
0163名無しさん@お腹いっぱい。2013/01/25(金) 11:46:54.65
ファイルの一行目だけ特殊扱いしてくれればいいんだけどな。
そういうLisp系のインタープリタある。(そもそもLisp系は行頭の#がちと特殊だが)
0164名無しさん@お腹いっぱい。2013/01/25(金) 13:38:52.29
>>162
2行目以降を使うスクリプトを書いてそれをシェバングにしたら?
0165名無しさん@お腹いっぱい。2013/01/25(金) 14:09:28.74
>>164
残念。
シェバングに指定できるのはバイナリだけ。(スクリプトじゃ駄目)
0166名無しさん@お腹いっぱい。2013/01/25(金) 16:53:20.52
>>165
じゃあperlかなんかで1行に凝縮させればおk
0167名無しさん@お腹いっぱい。2013/01/25(金) 16:57:50.64
あれ?バイナリじゃなくても動くぞ?
うちの壊れたか?
0168名無しさん@お腹いっぱい。2013/01/25(金) 17:47:21.06
shellが実行する場合もある。
0169名無しさん@お腹いっぱい。2013/01/25(金) 17:48:02.97
いずれにせよexecve(2)の中でやることだし、
最近は自分で処理するシェルもいるし。
0170名無しさん@お腹いっぱい。2013/01/25(金) 21:06:05.27
osascript は Leopard 以降なら sh-bang を理解するお。
0171名無しさん@お腹いっぱい。2013/01/25(金) 22:24:03.73
うろ覚えだけどbashの挙動は
とりあえずexec*してみる -> 駄目だったら/bin/bashで実行してみる
の2段構えだったような。
0172名無しさん@お腹いっぱい。2013/01/26(土) 13:02:07.76
FreeBSDだと #!インタプリタ にバイナリしか指定できないが、
Linuxだとインタプリタがスクリプトでも動くようだ。
0173名無しさん@お腹いっぱい。2013/01/26(土) 13:06:41.79
BSDはダメだな
ずいぶんと中途半端な意識だな
0174名無しさん@お腹いっぱい。2013/01/26(土) 17:08:04.37
>>172
だから、それはLinuxの機能じゃなくてbashの機能でしょ。
0175名無しさん@お腹いっぱい。2013/01/26(土) 17:11:06.38
_人人人人人人人_
> bashの機能 <
 ̄Y^Y^Y^Y^Y^Y ̄
0176名無しさん@お腹いっぱい。2013/01/26(土) 17:39:24.66
>>174
bashの機能じゃなくてカーネル(システムコール)のexecve(2)の機能なんだけど。
0177名無しさん@お腹いっぱい。2013/01/26(土) 19:52:37.75
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=fs/binfmt_script.c
0178名無しさん@お腹いっぱい。2013/01/26(土) 23:23:34.63
BSD系って結構厳密みたいだね。
#!/usr/bin/env PATH=/bin:/usr/bin:/usr/local/bin sh
のどこか適当なshを使ってという方法もできないような。
0179名無しさん@お腹いっぱい。2013/01/26(土) 23:31:57.82
それって厳密か?
0180名無しさん@お腹いっぱい。2013/01/27(日) 03:11:09.66
何を厳密といってるのか知らないけど、#!行ではオプションは一つしか指定できない。
↓これはダメ
#!/usr/bin/env PATH=/bin:/usr/bin:/usr/local/bin sh
0181名無しさん@お腹いっぱい。2013/01/27(日) 08:31:23.75
>>180
だから、それはFreeBSDの仕様じゃなくてashの仕様でしょ。
0182名無しさん@お腹いっぱい。2013/01/27(日) 08:38:44.48
_人人人人人人人_
>  ashの仕様 <
 ̄Y^Y^Y^Y^Y^Y ̄
0183名無しさん@お腹いっぱい。2013/01/27(日) 09:16:38.06
>>176
http://linux.die.net/man/2/execve
The interpreter must be a valid pathname for an executable which is not itself a script.
って書いてあるけど。

>>177
http://www.tamacom.com/tour/kernel/linux/S/11237.html#L19 だと
26 if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || (bprm->sh_bang))
27 return -ENOEXEC;
となってるので、仕様変えたのかな。

これ、
# cat /bin/aho
#!/bin/baka

$ cat /bin/baka
#!/bin/aho

とループしてたらどうなる?
0184名無しさん@お腹いっぱい。2013/01/27(日) 09:31:47.72
>>183
仕様変えた。Linuxでも古いカーネルだと#!/スクリプトは不可。

#!スクリプトがループしてた場合は単にexecve(2)がエラーになるだけ。
一応ループ判定はしてるみたい。
0185名無しさん@お腹いっぱい。2013/01/27(日) 09:43:22.30
>>183
スクリプトのネスティングが4回程度でエラーになるようになってるから、
ループしてたらそれでエラーになる。無限ループでハマることはない。
0186名無しさん@お腹いっぱい。2013/01/27(日) 10:16:14.90
なるほど、
>>177
25 if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') ||
26 (bprm->recursion_depth > BINPRM_MAX_RECURSION))
BINPRM_MAX_RECURSIONまでは再帰するのか。
>>183の例では/bin/aho, /bin/bakaの実行を何回も試みてBINPRM_MAX_RECURSIONに
達してやっとエラーか。 ダサッ
0187名無しさん@お腹いっぱい。2013/01/27(日) 10:42:07.89
シンボリックリンクのループ検出と一緒だろ。OSによらず。
2つだけでループしててもMAXに達するまでずっとたどってようやくエラー。
0188名無しさん@お腹いっぱい。2013/01/27(日) 12:47:54.49
そういえばそうだな。でも自己参照くらいはその場でチェックしてもいいだろ。
$ cat /bin/aho
#!/bin/aho
0189名無しさん@お腹いっぱい。2013/01/27(日) 12:52:21.55
その場でチェック()
0190名無しさん@お腹いっぱい。2013/01/27(日) 13:55:52.24
Patches Welcome
0191名無しさん@お腹いっぱい。2013/01/27(日) 14:29:29.40
そもそも自己参照していない正常なスクリプトの方が圧倒的に多いんだから、
自己参照をチェックするとそのオーバーヘッドが、全ての正常なスクリプトにも
負担させられることになって、実行速度がかえって遅くなるかと。
0192名無しさん@お腹いっぱい。2013/01/27(日) 16:42:35.29
ファイルからの読み込み行ってるんだから、スクリプトファイル名の比較の
負荷なんてゴミでしょ。
0193名無しさん@お腹いっぱい。2013/01/27(日) 17:04:30.10
>>192 のプログラマのセンスのなさはわかった。
0194名無しさん@お腹いっぱい。2013/01/27(日) 17:42:33.16
>>193
具体的に解説ヨロシク
0195名無しさん@お腹いっぱい。2013/01/27(日) 17:53:16.99
まずコードを書け、話はそれからだ
0196名無しさん@お腹いっぱい。2013/01/27(日) 18:21:24.09
>>195
だよな
>>193には具体的なコードを示す義務がある
0197名無しさん@お腹いっぱい。2013/01/27(日) 18:25:49.84
>>196
何を言ってるんだ?コードの話をしているお前ら全員だよ
0198名無しさん@お腹いっぱい。2013/01/27(日) 19:34:09.72
>>187
> シンボリックリンクのループ検出と一緒だろ。OSによらず。

シンボリックリンクのループ検出なんてある?
どういった場合に検出する?
0199名無しさん@お腹いっぱい。2013/01/27(日) 19:56:14.74
>>198
$ ln -s hoge /tmp/hoge
$ cat /tmp/hoge
cat: /tmp/hoge: Too many levels of symbolic links
0200名無しさん@お腹いっぱい。2013/02/12(火) 18:33:08.66
ttp://d.hatena.ne.jp/m-hiyama/20071221/1198221671
some-command 3>&amp;1 >/dev/null 2>&amp;3 3>&amp;- | less

1番の値が最終的にどこいったのがかわからんのです・・・
1→3→2とコピーされて標準エラー出力になるんじゃないの?
0201名無しさん@お腹いっぱい。2013/02/12(火) 18:46:22.72
>>200
1は/dev/nullだよ。
0202名無しさん@お腹いっぱい。2013/02/12(火) 18:53:12.63
>>200
1は3経由で最終的に2にコピーされて、その状態でsome-command が実行されてる、
で合ってるよ。

その「2にコピーされたもの」はパイプの入力だから、
結果的にsome-commandの標準エラー出力がパイプにつながる。

some-commandの標準出力は >>201 のとおり /dev/nullに捨てられてる。
0203名無しさん@お腹いっぱい。2013/02/12(火) 19:05:35.88
リダイレクトは左から順番に解釈していけば良いよ。
(1) 3は1(標準出力)に向けられる。
(2) 1は/dev/nullに向けられる。
(3) 2は3(標準出力)に向けられる。
(4) 3は閉じられる。
結果として
1は/dev/nullに2は標準出力に向いてる。
0204名無しさん@お腹いっぱい。2013/02/12(火) 20:55:57.35
再度質問です
shの機能で >>200 みたいに だーってリダイレクトが出来るじゃないですか
その文法から「1」が最終的にどこ行ったのか わーって追跡したいんです
出来ますの?勿論ググりましたが、当方馬鹿なのでわかりません
サルでも分かるような回答を強く期待します
僕はこういう小バカにしたような書き方しか出来ませんが、凄く切実に知りたいです
さぁどうぞ↓
02052002013/02/12(火) 21:09:43.68
うごごごご
0206名無しさん@お腹いっぱい。2013/02/12(火) 21:24:31.15
>>204
> aその文法から「1」が最終的にどこ行ったのか わーって追跡したいんです
ktrace とか truss とか strace ってのはダメ?
0207名無しさん@お腹いっぱい。2013/02/14(木) 11:04:26.66
シェル変数にコマンドを文字列として設定しておいて、それを実行したい。

CMD="printf '%x %x\n'" #これはダメ
$CMD 13 32
を実行して
printf '%x %x\n' 13 32
と同じ出力を得たい。
$CMD 13 32の行は変更不可。

CMD="printf '%x %x\n'"ではダメでした。
CMDにどのような文字列を与えると実現できるでしょうか?
bashの拡張機能を使ってもよいですが、なるべく使わない方向で。
0208名無しさん@お腹いっぱい。2013/02/14(木) 11:09:32.45
お題が不正確でした
> $CMD 13 32の行は変更不可。

$CMD 13 32

を含むシェルスクリプトがある。環境変数としてCMDを与えて
printf '%x %x\n' 13 32
と同じ出力を得たい。
CMDに
#!/bin/sh
printf '%x %x\n' "$@"
というスクリプトのパスを与える方法は思いつきましたが、スクリプトファイルを作成しないで実現したい。
0209名無しさん@お腹いっぱい。2013/02/14(木) 11:44:48.59
>>208
CMD='printf %x\040%x\n'

バックスラッシュが化けるので全角にしたので半角に直してね
■ このスレッドは過去ログ倉庫に格納されています