1 :
あらん :
2001/05/12(土) 18:32 シェルスクリプトを勉強しようと、思い様々な検索をかけてみて、 Windowsでいう、バッチファイルの高級バージョンという、事と、 主に、3種類のバージョンがあることは、わかりました。 しかし、肝心の勉強する本が見つかりません。みなさんは、 どのようにして、学ばれたのでしょうか。 オススメの、HP、本等ありましたら、お願いします。
google で検索する。
googleで検索したんですが、肝心の参考書はみつかりませんでした。 2さんが、ご存知でしたら是非おしえてください。m(._.)m
4 :
名無しさん@お腹いっぱい。 :2001/05/12(土) 19:42
5 :
名無しさん@お腹いっぱい。 :2001/05/12(土) 19:50
>>1 なんこう、他力本願なんだ?
manみれ。
例は、自分のホストのinitでも覗け。
せめて何shを使うのかくらい言えばいいのに。 そもそもOSは?
7 :
名無しさん@お腹いっぱい。 :2001/05/12(土) 20:14
『プロフェショナルシェルプログラミング』 (砂原秀樹他著 アスキー出版局 1996年発行) が、入門〜中級向けくらいにいいんじゃないのかな。 魂的には、『UNIX プログラミング環境』が好きだけど。
8 :
名無しさん@お腹いっぱい。 :2001/05/12(土) 20:30
9 :
名無し産 :2001/05/12(土) 20:50
入門UNIXシェルプログラミング ソフトバンク ISBN4-7973-0828-1 とりあえず、立ち読みな
10 :
名無しさん@お腹いっぱい。 :2001/05/12(土) 22:02
cshの $file:r とか便利で使いたくなるんですけど。 まあ、basenameとか expr使えばいいんだけど。 コマンド起動するぶん遅くなるし。 [ よりも caseを使え。
11 :
名無しさん@お腹いっぱい。 :2001/05/12(土) 22:18
man sh
12 :
名無しさん@お腹いっぱい。 :2001/05/12(土) 23:34
man ページだけでは shell プログラミングはできない。 せいぜい DOS のバッチと同じレベルで終ってしまう。 とりあえず、ここにあがっているような書籍を読んで、 /etc/rc とか shutdown スクリプトなどを手始めに手当り次第解析しろ。 あと、リダイレクトや echo * の意味を完全に理解しておけ。 # 特に DOS 出身者じゃなくても周りに DOS 出身者がいたら、 # 混乱させられるから注意しろ。 # あ、ここでの DOS 出身者とは「DOS と同じジャン」っていうヤツを示す。
オレはAIXなのでオライリーの「入門Kornシェル」です。 かなりいいです。
14 :
名無しさん@お腹いっぱい。 :2001/05/13(日) 00:11
|| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|| || BSD馬鹿は Λ_Λ いいですね。 || 放置! \ (゚ー゚*) ||________⊂⊂ | ∧ ∧ ∧ ∧ ∧ ∧ | ̄ ̄ ̄ ̄| ( ∧ ∧ ( ∧ ∧ ( ∧ ∧ | | 〜(_( ∧ ∧ __( ∧ ∧__( ∧ ∧ ̄ ̄ ̄ 〜(_( ∧ ∧_( ∧ ∧_( ∧ ∧ は〜い、先生。 〜(_( ,,)〜(_( ,,)〜(_( ,,) 〜(___ノ 〜(___ノ 〜(___ノ
*BSD を使いこなせない厨房発見!
16 :
名無しさん@お腹いっぱい。 :2001/05/17(木) 16:30
solarisでjavaの複数のプロセスを一気に消したい。 % ps PIT TT S TIME COMMAND ってでてきます。 で、 % ps | awk ' $5 ~ /java/ { print $1; }' とやると、COMMANDにjavaを含むプロセスのPIDを表示しますよね? で、そいつらを消したいのですが。
17 :
名無しさん@お腹いっぱい。 :2001/05/17(木) 16:38
# kill -KILL 1 で全部消えますよ
18 :
名無しさん@お腹いっぱい。 :2001/05/17(木) 17:25
Solaris はしらんけど、 % kill `ps | awk ' $5 ~ /java/ { print $1; }'` でどうよ。
19 :
名無しさん@お腹いっぱい。 :2001/05/17(木) 17:31
Solaris に pkill って便利なのあるよ。 あ。pgrep ってのも。
20 :
16 :2001/05/17(木) 22:08
21 :
名無しさん@お腹いっぱい。 :2001/05/17(木) 22:36
オレも
>>7 をお薦めするよ。インタラクティブな用法と、
プログラミング、それぞれを分けた上でキッチリと攻めて
いるので判りやすいし、お得感もある。
シェルプログラミングって、空白や改行が不自由だったり
文法にきつい制約があったりするから、perlなんかを
自由に扱える人でも頭を抱えてしまうことが多し。
けっこう奥が深い世界なんだよね。
ねうねう、 ユーザー大量追加のスクリプトって組めなくは無いですよね どなたか見本を教えてくださらない? つーか、たとえばhoge.csvファイルで 中身はhoge,xkfo07034のようにID,Passに記述されているとしたら・・・ すんません厨房で・・・
23 :
名無し侍 :2001/05/20(日) 12:38
あげとけ
24 :
名無しさん@お腹いっぱい。 :2001/05/20(日) 13:33
>>12 いろんなツール類を組み合わせれば、DOSのバッチでもかなりのことが出来ますね。
バッチっていっても、単なる起動バッチの類から、Cマガに昔載ってたプラグラム(だっけ?)みたいな割と複雑なものまで色々ありますね。
ECHOを使って、バッチからバッチを自動生成したりとか。
環境変数やリダイレクトもよく使うし、findやforeach、awk,sortf,sedなども良く使います。
多分「DOSと一緒」という発言は↑のような使い方を前提としていると思うんですが、「決定的な違い」というのが良く分からないんです。
シェルスクリプトの方がもっと高機能だと思うんだけど、まだ手習いなもので。
素人目だと、プロセス管理とか、分岐処理とかがやり易いのかなあっていうぐらいしか分からないです。
あ、例えばパイプ処理が並列で行われているとか、それに伴う途中経過の違いとかいうのは分かるんですけど、実用上、
具体的にこんな違いがあるっていうのが、どうもピンと来ないんです。
バッチとシェルスクリプトの決定的な(ツール程度では埋めようの無い)、実用上の相違点を、具体的に幾つか挙げていただけると嬉しいです。
もちろん煽りじゃないです。
command.com氏ね Winにもshを標準搭載して欲しい
26 :
名無しさん@お腹いっぱい。 :2001/05/20(日) 14:48
>>24 awk と、perlとの違いみたいなモンでしょ。
短いときはそんなにかわらんし、長くてもその気になりゃ
どうにかなるけど、同じことをするのに必要な労力が違う。
あ、スクリプトじゃないけど、一つだけ。
DOSを書き込み保護したフロッピーで起動して、
CD-ROMかなんかのファイルをパイプして加工して表
示させようとしたとき、
「ディスクに書き込めませんだぁ?なめんなぁ!!!」
それまで、command.comが一時ファイルつくるのしらんかった。
HDDがトラブってリカバリ中だったから、えらい困った
同じ理由で、マルチタスクじゃないってのはイタイな。
そういや、コマンドが戻り値を返さないのもダメ。
なんだ、結構あるか。
>>23 for i in `cat csvファイル`
do
awkできりわけ
ユーザー登録コマンド
done
27 :
名無しさん@お腹いっぱい。 :2001/05/20(日) 16:35
>>26 おお!ありがとうございです!!
ちょっとやってみます
さすが2chはえー
>>26 書込み保護FDからDOS起動すると
A:\>type hoge.txt | more
すら使えなくてナ。
# command.com sage
hoge.ext | more ができるのに、 hoge.bat | more ができない、そんな DOS を愛してます。
そうそう、いちいち直交性がないんだよな..>>DOS c:\windows> cd d: ってやっても、カレントディレクトリが変わってなくて びっくりするし。
31 :
名無しさん@お腹いっぱい。 :2001/05/20(日) 23:02
/ ̄ ̄ ̄ ̄ ̄ | はやくこの板が | あらし厨房だらけになって ,__ | 逝ってくれますように / ./\ \_____ / ./( ・ ).\ o〇 ヾ!;;;::iii|//" /_____/ .(´ー`) ,\ ∧∧ |;;;;::iii|/゙  ̄|| || || ||. |っ¢..|| ̄ (,, ) ナムナム |;;;;::iii| || || || ||./,,, |ゝ iii~ ⊂ ヾwwwjjrjww!;;;;::iii|jwjjrjww〃 | ̄ ̄ ̄|~~凸( ̄)凸 .( ,,)〜 wjwjjrj从jwwjwjjrj从jr
32 :
12 :2001/05/21(月) 19:18
12 です。
>>24 さんはわかっておられるようですが、
DOS と sh との echo * の違いなども開発時のチョイツールを作ったときに
いらいらします。
自作の sed -e 'hogehoe' なんて処理は
#!/bin/sh
cat $* | sed -e 'hogehoge'
としておくだけでも使い道は広がります。
ps | filter とか filter data/* のどちらも OK でしょ。
標準エラー出力ないのも DOS の弱点です。(WinNT 系はあるようですが)
hoge.exe > test1 としたとき、
Usage: hoge.exe [-options]
なんてファイルが作られるとかなり萎えます。
sh では hoge > test1 としてもエラーは tty(画面)に出力されるし、
同様に安心して hoge | mail foo@bar も出来る。
だから、
echo "Usage: hoge [-options] [file ...]" はダメ。
echo "Usage: hoge [-options] [file ...]" >&2 とすべし。
C でも printf(...) でなく、fprintf(stderr, ...) と書くべし。
となるのです。
33 :
名無しさん@お腹いっぱい。 :2001/05/21(月) 20:40
csh系でスクリプト作るやつはヴァカという おなじみの煽りがまだないな。
>>33 言うまでも無いことでしょ
別に煽る必要は無いもの
35 :
名無しさん@お腹いっぱい。 :2001/05/22(火) 00:09
ほんとにそうかなぁ。 高々数10ステップのスクリプトだったら、csh でもいいじゃん。 ただの都市伝説じゃないの?
36 :
22(偽) :2001/05/22(火) 00:17
>>26 つーか具体的なソースを教えてくださいよー
今度50人追加しろっていわれてるんだよー
なぜかおいらなんだよー
すみません
できれば真珠で…
ぁぅぁぅ〜
37 :
名無しさん@お腹いっぱい。 :2001/05/22(火) 00:21
>>35 同意。csh のマズいところをちゃんと理解して、
csh でも問題ない局面で使うんならおっけーだろ。
なんでもかんでも No! っていうアホがいて困るんだよね。
つーか、csh 使いはふつー .xsession を csh で書かないか?
38 :
名無しさん@お腹いっぱい。 :2001/05/22(火) 00:35
>37 同意。すぐに右へならえで真似して言い出すんだよな。 自分で判断することが出来ないっていうか。 んでシェルスクリプトだけど, そんなに今時シェルスクリプトが多用される局面ってあるの? 俺はシェルスクリプトはそんなに詳しくない。 ちょっとした事ならrubyで書くし。
39 :
名無しさん@お腹いっぽい。 :2001/05/22(火) 01:20
>>33 >>8 参照。。。
けど、なぜ?<cshはヴァカ
tcshはどうなん?
40 :
名無しさん@お腹いっぽい。 :2001/05/22(火) 01:29
>>26 >そういや、コマンドが戻り値を返さないのもダメ。
たしか戻り値あったと思うけど?
じゃないと if errorlevel の意味が無い…
41 :
名無しさん@お腹いっぱい。 :2001/05/22(火) 01:43
csh系でスクリプト作るやつはヴァカ
42 :
名無しさん@お腹いっぱい。 :2001/05/22(火) 02:01
コマンドの羅列だったら別にcsh scriptでもなんでもいいけど。 csh scriptって関数も使えないし。
43 :
名無しさん@お腹いっぱい。 :2001/05/22(火) 07:40
>>37 俺login shellはtcshだけど、.xsessionその他スクリプトのたぐいは
全部bourne shellだし、コマンドラインで難しいことするときはsh -c
から始めるけど…
44 :
名無しさん@お腹いっぱい。 :2001/05/22(火) 10:45
cd / file /bin/* /sbin/* /usr/bin/* /usr/sbin/* | grep Bourne | wc FreeBSD4.3では Bourne shell 43 perl script 30 全部 747 でした。perlよりshell scriptのほうが多いとは知らなかった。
45 :
35 :2001/05/22(火) 13:53
35 です。(じつは
>>12 だったりもする)
| 高々数10ステップのスクリプトだったら、csh でもいいじゃん。
なのですよ。「関数がない」とか、「標準エラー出力へのリダイレクトが出来ん」とかは
そのとおりなのだが、shell プログラムへの登竜門という意味でもよいと思う。
使い捨てのスクリプトなら csh でもよいかと。
% echo "私も他人に参照されるのは sh で書いてます(逃)" | sh -c 'cat 1>&2'
46 :
37 :2001/05/22(火) 15:03
そういえばまだ出てないね。なぜ csh で書くのがよくないか。↓
http://www.klab.ee.utsunomiya-u.ac.jp/~hiroki/csh-whynot.euc 逆に言えば、スクリプト中でここで挙げられているようなことを
しないのであれば、csh でも特に問題なし。
>>43 #!/bin/csh で .xsesssion を書くと(#!/bin/csh -f にあらず)、
いちいち指定しなくても .xsession から起動されるいくつものアプリが
すべて .cshrc に記述されたパスや環境変数を引き継いでくれるので、
これに限っては #!/bin/sh で書くよりメリットが大きいと思う。
まあ、かく言う俺も、.xsession と .cshrc 以外はすべて sh で書くけどな(藁
csh の欠点に気を使いながらスクリプトを書くぐらいなら、はじめから
sh で書いた方がマシ。
cshの文法忘れちゃった。
49 :
名無しさん@お腹いっぱい。 :2001/05/23(水) 14:56
$ file /bin/* /sbin/* /usr/bin/* /usr/sbin/* | grep 'c shell' /usr/bin/vgrind: C shell script text 僅かに存在。
50 :
名無しさん@お腹いっぱい。 :2001/05/23(水) 16:34
>>40 そうっすよね。わざわざreturn()しないことに意味があるかなー。
51 :
q :2001/05/28(月) 15:01
bshを使っているのですが 数値を格納してある変数の内容をいつも5桁に、 たとえば n = 10 → 00010 n = 111 → 000111 という風に保持、または出力時にだけ そのような形にして出力できるようにしたいのですが どうすれば良いでしょう? 桁数を調べるコマンドとかありますか?
52 :
37 :2001/05/28(月) 15:21
000111 は6桁に見えるが気のせいか? $ n=10 $ echo $n 10 $ printf '%05d\n' $n 00010 $ echo 00000$n | sed 's/.*\(.....\)$/\1/' 00010
53 :
名無しさん@お腹いっぱい。 :2001/05/28(月) 21:27
古いつっこみだが、
>>25 もしWin2000使ってたら一度
>if /?
>for /?
>exit /?
>call /?
とかやってそれぞれのヘルプ見てごらん。DOSの頃からすると死ぬほど
拡張されていて目が点になるから。
# でも行き当たりばったりな拡張で文法滅茶苦茶だし、かゆい所に手が
# 届かないダサい仕様で「素直にsh使わせろゴルァ!」と思うけど(w
>>53 あくまで推測ですが、そりわcmd.exeでわ亡いかと。
いや、MS-DOS6.2/V以来使ったことないんで、ホントに推測ですが。
と、上をみながら逝ってみる
「 ・_ D |
| ・ /
|:-D;
56 :
Manual & Reference」 ISBN4-87966-865-6 定価 (本体 2400円+税) 秀和システム ホントの初歩、簡単な例、マニュアル。 これで、bash ならほとんどOKと思われ。 :
57 :
七資産 :2001/06/24(日) 22:29
cshも関数が使えるといいんだけど。。。 標準エラーを、ファイルに落とすときは、bsh系よりも、csh系の方が 楽なんだけどね。。。 ファイルディスクリプタの制御をとるか、簡便さをとるか。。。 TPOにあわせてってとこか。。。
古い話だが
>>53 Win32 なら WSH 使うでしょ。言語も JScript ならかなりまともだし、
ActiveX コントロールを呼び出せるから Cygwin なんかの sh より
も使い勝手が良いよ。
59 :
名無しさん@お腹いっぱい。 :2001/07/08(日) 14:37
bashにtcshのコンプリートみたいなのありますか? たとえば、javacには、*.javaしか反応しないとか。
60 :
名無しさん@お腹いっぱい。 :2001/07/08(日) 15:18
completionはあるけど、tcshみたいに強力じゃない。
ありがとうございます。 zshスレもあるので、zshでも使おうかと思います。
62 :
名無しさん@お腹いっぱい。 :2001/07/10(火) 09:49
最近来るようになったので化石レス
>>1 sharの出力とか、comp.unix.shellとかが結構いいかと。
僕はそういうのとman shで自習しました。
>>5 Linuxのinitとかbashでゴリゴリ書いてあって最悪なので、
今一汎用的な題材にはならないかなと。もちろん題材に
適したinitもあるのは分かってますけど。
>>24 evalと`がないのが辛いです。後、shのifなんかはその後のコマンドを
実行した結果で動作を変えるので、if [ $i = 10 ]; thenとか
if grep $pat $data; thenとか、if perl -e $script $data; thenとか
なんでも組み合わせれる、その自由度が好きです。
>>45 cshは括弧や改行を強制されるのが嫌っす。
>>52 exprももっと使ってあげましょう。
$ expr 00000$n : '.*\(.....\)'
00010
63 :
名無しさん@お腹いっぱい。 :01/09/01 15:19 ID:Kh4c3TBg
ログインシェルがtcshだから、最低限bashを起動するまでの 処理くらいはcshで書けるようになりたいんだけど、 man cshを読むのはつらすぎるし、かといってパクるべき スクリプトも少ない・・・ とりあえずコピペで単純にbashを起動するだけのものは 出来たけど、それ以上のことをやるために、わざわざ shのスクリプトを書いて、環境変数を設定するcshスクリプトを 生成させて、.cshrcからsourceしたりと、相当バカ臭いこと やる羽目になっている。 どこかにいいサイト無いかな。
64 :
名無しさん@Emacs :01/09/02 03:14 ID:ok8jFRRg
>>63 > ログインシェルがtcshだから、最低限bashを起動するまでの
> 処理くらいはcshで書けるようになりたいんだけど、
~/.login に
exec /usr/local/bin/bash -c "exec -l /usr/local/bin/bash"
じゃだめか?
66 :
名無しさん@お腹いっぱい。 :01/09/02 11:36 ID:c/03xBX6
chsh不可なので、 if ( $?prompt == 1) then exec bash endif とするしかない(のだそうだ)。 で、その前にいろいろ環境変数がらみで小細工するべく、 (TERMを見るとかXのフォワーディングの有無を調べるとか) login.sh source environ.csh (environ.cshはlogin.shで生成) という暴挙に出ているわけ。
67 :
名無しさん@お腹いっぱい。 :01/09/02 12:40 ID:YcKhn1C2
#! /bin/sh /usr/local/bin/giko2mona `ls /var/sage/` 自作のPerlスクリプトgiko2monaに、/var/sage/配下の*.txtを 引数として渡したいんですが、あってますか? って言うか、うまく動かないのよ(/var/sage/のファイル一個しか渡せない)
>>67 その自作スクリプトの方で複数パラメータにちゃんと対応してるの?
69 :
名無しさん@お腹いっぱい。 :01/09/02 12:56 ID:YcKhn1C2
>>68 >複数パラメータ
これの意味すらワカランので逝って良しですな・・・・
71 :
名無しさん@お腹いっぱい。 :01/09/02 16:06 ID:c/03xBX6
そもそも複数パラメータに対応していたらシェルスクリプト 要らないだろ。aliasで十分。しかもlsも要らない。 ワイルドカードがどうやって展開されるのか勉強した方が いいだろう。 ファイル1個しか渡せないと言うなら、giko2monaの方では 最初に与えられたパラメータしか解釈しないで、他は無視する 仕様になっているようだから、シェルスクリプト側で対応するなら #!/bin/sh for file in /var/sage/*; do test -f "$file" && /usr/local/bin/giko2mona done giko2monaの方をいじってもいいけど。
おっと、/usr/local/bin/giko2mona "$file"だった。
73 :
名無しさん@お腹いっぱい。 :01/09/03 04:57 ID:NF.CDf1M
「df」や「vmstat」のコマンドで表示されるモノを、 echoで表示させるにはどうすればいいのでしょうか。
74 :
73 :01/09/03 05:51 ID:NF.CDf1M
ここで書き込んだ後、書き込みが反映されてなかった ようなんでLinux板で同じ書き込みしちゃいました。 73番は無視しちゃってください。。。 この板は書き込んだ後ラグがあるのかな?
75 :
名無しさん@お腹いっぱい。 :01/09/03 17:03 ID:AMWgM1Ug
日付(文字列)から年齢を求めるのに一番スマートな方法ってなんですかね?
% expr `date +%s` - `date --date 1970/1/23 +%s` | awk '{print strftime("%Y", $0)-1970}' 31 うーん、スマートじゃないなぁ。別解求む。 これだと1969年以前の生まれは計算できないかと思いきや、 1934年までは大丈夫だった。けっこういい加減らしい。> GNU date
77 :
名無しさん@お腹いっぱい。 :01/09/05 10:18 ID:ati0G6T2
echo で番号つきのメニューを表示し, 数字の入力をうながして, 入力された数字に応じた処理をシェルスクリプトで 実現するにはどのようにしたらいいのでしょうか?
78 :
名無しさん@お腹いっぱい。 :01/09/05 11:04 ID:afdg/tE2
>>77 #!/bin/sh
echo "input 1 or 2"
read n
case "$n" in
1)
echo "selected 1"
;;
2)
echo "selected 2"
;;
*)
echo "error"
esac
return 0
79 :
名無しさん@お腹いっぱい。 :01/09/05 11:07 ID:afdg/tE2
最後のreturn 0 はいらんかった。うちゅ。
80 :
77 :01/09/05 13:09 ID:ati0G6T2
保守あげ
82 :
名無しさん@お腹いっぱい。 :01/09/14 17:15
指定したディレクトリ以下にある, 指定した(複数の)拡張子のファイルのみを できればディレクトリ構造を保ったまま 圧縮したいのですけど, そのようなシェルスクリプトはどのように書けばいいのでしょう?
83 :
名無しさん@お腹へった。 :01/09/14 17:41
# usage: command <tar_filename> <dir> <suffix1> [<suffix2> ..] TARF=$1 shift DIR=$1 shift rm $TARF ${TARF}.gz for i in $* do tar rvf $TARF `find . -name "*.$i"` done gzip $TARF
84 :
名無しさん@お腹へった。 :01/09/14 17:43
# cd 忘れた。 # usage: command <tar_filename> <dir> <suffix1> [<suffix2> ..] TARF=$1 shift DIR=$1 shift rm $TARF ${TARF}.gz cd $DIR for i in $* do tar rvf $TARF `find . -name "*.$i"` done gzip $TARF
85 :
名無しさん@お腹いっぱい。 :01/09/14 20:59
>>84 も悪くはないケド
find . \( -name \*.txt -o -name \*.doc -o -name \*.html \) -print | xargs tar cf - | gzip -v9 > hoge.tgz
で、コマンドライン一行で済むYO!
(でもちょっと長いか…)
>85 ファイル数が多くてxargsがtarを分割しちゃったら終わる……
87 :
名無しさん@お腹いっぱい。 :01/09/16 00:31
>>75 うつくしくないかな・・・
#!/bin/sh
if [ $# -eq 1 ]
then
currentdate=`date`
birthdate=$1
elif [ $# -eq 2 ]
then
currentdate=$1
birthdate=$2
else
echo "usage: countage [curennt] birthday"
exit 1
fi
currentyear=`date -d $currentdate +%Y`
currentmonth=`date -d $currentdate +%m`
currentday=`date -d $currentdate +%d`
birthyear=`date -d $birthdate +%Y`
birthmonth=`date -d $birthdate +%m`
birthday=`date -d $birthdate +%d`
if [ $currentmonth -gt $birthmonth ]
then
age=`expr $currentyear - $birthyear`
elif [ $currentmonth -eq $birthmonth ]
then
if [ $currentday -ge $birthday ]
then
age=`expr $currentyear - $birthyear`
else
age=`expr $currentyear - $birthyear - 1`
fi
else
age=`expr $currentyear - $birthyear - 1`
fi
echo $age
88 :
名無しさん@お腹いっぱい。 :01/09/16 00:40
訂正。 4c4 < currentdate=`date` --- > currentdate=`date +%Y/%m/%d`
89 :
operator :01/09/16 02:40
>>86 find . \( -name \*.txt -o -name \*.doc -o -name \*.html \) -print | tar -cT - -f hoge.tar.gz
-T使えない人はゴメン
保守
91 :
名無しさん@お腹いっぱい。 :01/12/12 23:37
age
92 :
名無しさん@お腹いっぱい。 :01/12/12 23:52
one linerだと、空白の含まれたファイル名が面倒だね。
93 :
名無しさん@お腹いっぱい。 :01/12/13 00:27
>>92 find . \( -name '*.txt' -o '*.doc' -o '*.html' \) -print0 | xargs -0 tar cf - | gzip -cv9 > hoge.tgz
94 :
名無しさん@お腹いっぱい。 :01/12/13 12:36
シェルスクリプトで,.やsourceを使わずに環境変数を変えられますか? また,tcshでインタラクティヴなスクリプトを書きたいんですけど,sh系のreadに当たるものはないんでしょうか.
>>94 > シェルスクリプトで,.やsourceを使わずに環境変数を変えられますか?
何がしたいんですか?
96 :
スクリプト初心者 :01/12/13 19:41
#!/bin/sh PATH="/usr/bin:/usr/ucb" export PATH ME=`basename $0` # my name. FING_OPT="-s" # default option for finger (short format). for i in "$@"; do # parse option. case $i in -l) # output finger with long format. FING_OPT="-l" ;; -s) FING_OPT="-s" # output finger with short format. ;; -h|*) # output usage. echo "usage: $ME [-l|s] [-h]" >&2 exit 1; ;; esac done for i in `ls /home2/a54`; do finger $FING_OPT $i done でbasenameを利用している理由がわかる人はいますか??
basenameを初めて知って、試しに既存のスクリプトに 適用してみたとか?
CLASSPATHを変えるとともに,shellの初期化ファイル(.tcshrcなど)を書き換えるスクリプトを書いたんです. Shellの初期化ファイルは.ってやらなくても変えられますが,今いるshellは変わってくれないので・・. .とかやらずに済むほうがいいなあと思ったんですが.
ああ,それから,tcshでreadにあたるものは自己解決しました.
UNIXシェルについて教えてください。 /home/log というディレクトリに test.logというログファイルがあるとします。 そのファイルをシェルスクリプトのループ文内で 1行ずつprintさせるには、どのようなコマンドを書けば 1行ずつ表示されますか? 教えてください。 お願いします。
すいません。 1行ずつprintさせるというよりも 1行ずつ変数に入れる間違いです。 for hensu in (XXX) do print $hensu done XXXに入るコマンドを教えてください。 foreachを使うんでしょうか?
for hensu in `cat filename` do print $hensu done ` はバックスラッシュ
返答ありがとうございます。 filenameの1行目が例えば・・・。 「aaa bbb ccc ddd」とスペース区切りでも hensuの中身を表示させると・・・。 print $hensu →aaa bbb ccc ddd ・・・となるんですよね?あ
あ。まちがい。 #!/bin/sh IFS=" " for i in `cat kyo.log` do echo $i done に訂正。
#!/bin/ksh exec 3< /home/log/test.log while read -u3 i do echo $i done exit 0
sh, csh, ksh, tcsh, bash, zsh の機能比較をしているサイトないでしょうか。 MacOS X の tcsh はコマンドをタイプミスすると正しいコマンドを推測して候補を 挙げてくれるんだけど、これって何ていう機能でどうやって実現してるのですか? ksh, bash, zsh 辺りで同様の機能を実現する事は可能ですか? 可能ならポインタだけでも教えてください。 先生、お願いします。
zsh 最強。 とか言ってみるテスト。
>>101 zsh は拡張多すぎて訳分からんですよ。
zsh 使って
>>100 の答えをお願いしますですだ。
正しいコマンドの候補を挙げさせる方法でござるよ。
間違った。
>>109 zsh は拡張多すぎて訳分からんですよ。
zsh 使って
>>108 の答えをお願いしますですだ。
正しいコマンドの候補を挙げさせる方法でござるよ。
>>100 さん、忝い。
他は知らんがzshだと % rop [~] zsh: correct 'rop' to 'top' [nyae]? y んでyを選べば正しいのになる
ってか、これシェルスクリプトとはあんまり関係ないよな。
tar xzvf [TAB] の時、選択肢に*.gzを選んでくれるのはzshの機能なのかな。 ちゃんと atr xjvf [TAB] と時は*.bz2を選んでくれる。 シェルスクリプトとは関係無いのでsage
115 :
名無しさん@お腹いっぱい。 :01/12/27 01:38
>>112 ならないけど、初期設定ファイルに何か書く必要ある?
やり方教えて
ageましょう
117 :
名無しさん@お腹いっぱい。 :02/01/11 17:56
csh はなぜ「使うな」と言われているんでしょうか? 失敗談キボーン
>>117 便利な生活の為にチョコ書きすんなら
こまけーこと気にしないでダイジョブ
ただ実害の要点をふまえて書けば良いんじゃないの。
鬼の要にスクリプト職人になるならボンシェルの方がいいのかもな
まぁ過去ログくらい全部読みなさいってこった。
仕事の前例が csh なのでそのまま逝くしかない。
cshがなぜ悪いのか理解して、cshでも問題ない用途に使うならまったく問題なし。 頭ごなしにcsh使うなshで書けと言う方がアホ。 もちろん、cshで面倒なことでもcshでやろうとするのはアホ以下。
122 :
名無しさん@お腹いっぱい。 :02/02/13 00:23
初めて書いたスクリプト(プログラム)です。とりあえず期待どおり動くのですが どうもスマートじゃないみたい。先輩がた添削お願いします。 #!/bin/sh # # aptのsource変更を簡潔に行うスクリプト。 # aptctrl (woody | testing) => aptのsourceをtestingへ # aptctrl (sid | unstable) => aptのsourceをunstableへ # backup cp /etc/apt/sources.list /etc/apt/sources.bak # temp作成 cp /etc/apt/sources.list /etc/apt/sources.tmp # 引数の数チェック if [ $# -eq 0 -o $# -gt 1 ]; then # 0個もしくは2個以上ならエラー。usage表示して終了 echo 'aptctrl is script to easy-setting /etc/apt/sources.list' echo 'usage: aptctrl ( (woody | testing) | (sid | unstable) )' exit 1 # 引数の内容チェック elif [ $1 = woody -o $1 = testing -o $1 = sid -o $1 = unstable ]; then # 変数sssへ引数を代入。(woody|testing)若しくは(sid|unstable)か判定 # sss="#"を除く 、aaa="#"を付加する sss=$1 if [ $1 = "woody" -o $1 = "testing" ]; then sss="testing" aaa="unstable" elif [ $1 = "sid" -o $1 = "unstable" ]; then sss="unstable" aaa="testing" fi # どちらへ変更するか表示 echo ${sss} # sedによりdebian.org + (testing | unstable)を含む行の先頭の"#"を置き換え sed -e "s/^#\(.*debian\.org.*\) ${sss}\(.*\)/\1 ${sss}\2/g" /etc/apt/sources.tmp > /etc/apt/sources.tmp2 sed -e "s/\(^deb.*debian\.org.*\) ${aaa}\(.*\)/#\1 ${aaa}\2/g" /etc/apt/sources.tmp2 > /etc/apt/sources.list # tempファイル削除 rm -f /etc/apt/sources.tmp* else # 引数が(woody|testing)若しくは(sid|unstable)以外の場合はエラー表示。 echo "argment error: woody or sid please." fi
123 :
リックトム :02/02/13 01:34
教えてください。 例↓ aaa="test /home/test/log/*.log xxx yyy" cnt=1 for bbb in `print $aaa` do print $bbb (( cnt=$cnt+1 )) done exit 0 上記のスクリプトで、$aaaをスペース区切りで >test >/home/test/log/*.log >xxx >yyy とprint出力したいのですが cnt=2の時の$bbbの出力の際に 変数bbbを単なる文字列の"/home/test/log/*.log"とせずに /home/test/logのディレクトリの中にある*.logにマッチする 全てのファイル名を出力してしまうんです。 文字列として、/home/test/log/*.log"と出力するには どうしたら良いのでしょうか? 乱文申し訳ありません。
まずシェルに関係ない部分から。 ・引数処理に一貫性がなく分かりにくい。 $1の中身のチェックが外側のelifと内側のif...elif で二重に行われているのは見通しが悪い。 ・変数名がaaa,sssじゃ何なのかすぐに分からない。 ・usageの表記が一般的でない。(括弧の使い方とか) woody|testing|sid|unstableみたいに書くとか、 ただversionと書いて2行目に候補を書くとかにする。 ・最初のsss=$1は何のため? ・sources.tmp2だけでいいのでは?sources.tmpは 書き換えられていないようだが。 次にシェルスクリプトとして。 ・testで-oをわざわざ並べなくとも、case文でwoody|testing) みたいに書ける。 ・$1がきちんと""で囲まれていない。 ・sedで相当トリッキーなことをやっているが、分かりにくいし、 GNU版以外のsedでも動くとは限らない。awk使え。 ・細かいことだが、バックアップはcpよりmvのほうが タイムスタンプが変わらなくてgood。
124は>122ね。 >123 aaa="test '/home/test/log/*.log' xxx yyy" では駄目?つーかなぜprint?
>>124 先輩指摘ありがとう!
とりあえず今日は寝ます。
明日書き直して書き込みます。
よろしこ。
127 :
リックトム :02/02/13 01:56
>つーかなぜprint? やりたい処理は、ちょっと違うんですが 変数に代入する時に、printコマンドを使っているので・・・。 test /home/test/log/*.log xxx yyy この各フィールドを変数に代入したいのです。
>>124 タイムスタンプ変わらないんだったらcp -pでもいーじゃん
129 :
名無しさん@お腹いっぱい。 :02/02/13 07:32
128さんに一票
>>128 cp -p だと、
i-nodeが変わってしまう。
ハードリンクが切れてしまう。
本題からそれるが、ファイルのバックアップなら、
mvしてからcp -pで戻すのが最良。
>>130 それだと一瞬ファイルが存在しなくなる。
inode number の保存までこだわるなら
ln file bakup
cp -p file tmp
mv tmp file
かな。
まあsources.lst程度にそこまでの安全性を 求めなくても・・・
書き直してみました。
>>124 さんの指摘の内、sedでなくてawk使え、は納得いきませんです。
なるべくシステムへの負担を最小限に抑えるという観点からはsedでいいのでは?
Ruby > Perl >>> awk >>>>> sed (負荷の大きさ) と勝手に認識しているのですが。。。
あとバックアップの件は勉強不足なのでとりあえずcp -pで。
#!/bin/sh
# aptctrl -- aptのsources.list変更を簡潔にコントロールするスクリプト。
# DATE:2002/02/12 AUTHOR:shinmai
# aptctrl (woody | testing) => aptのsourceをtestingへ
# aptctrl (sid | unstable) => aptのsourceをunstableへ
# backup
cp -p /etc/apt/sources.list /etc/apt/sources.bak
# temp作成
cp -p /etc/apt/sources.list /etc/apt/sources.tmp
# 引数の数チェック
if [ "$#" -eq 0 -o "$#" -ge 2 ]; then
# 0個もしくは2個以上ならエラー。usage表示して終了
echo '$ID: aptctrl v0.01 2002/02/13 by shinmai'
echo 'Usage: aptctrl woody|testing|sid|unstable'
echo 'aptctrl is a script to easy-configure /etc/apt/sources.list'
exit 1
fi
# 引数の内容チェック
case "$1" in
# (woody|testing)の場合
woody|testing )
echo "set to testing(woody)."
comment="unstable"
uncomment="testing"
;;
# (sid|unstable)の場合
sid|unstable )
echo "set to unstable(sid)."
comment="testing"
uncomment="unstable"
;;
# 上記以外の場合はエラー。引数の説明を表示して終了
*)
echo 'argment error: "woody" or "sid" please.'
exit 1
;;
esac
# sedによりdebian.org + (testing | unstable)を含む行の先頭の"#"を置き換え
sed -e "s/^#\(.*debian\.org.*\) \(${uncomment}.*\)/\1 \2/g" /etc/apt/sources.tmp | sed -e "s/\(^deb.*debian\.org.*\) \(${comment}.*\)/#\1 \2/g" > /etc/apt/sources.list
# tempファイル削除
rm -f /etc/apt/sources.tmp
>
>>124 さんの指摘の内、sedでなくてawk使え、は納得いきませんです。
>なるべくシステムへの負担を最小限に抑えるという観点からはsedでいいのでは?
この程度の負荷なんてクソみたいなものだから、
そんなことよりもメンテナンスのしやすさを重視すべき。
もっとも、awk では正規表現でマッチした部分文字列を \1 \2 で参照できず、
ほかの手段を用いる必要があるので、awk を使うとなるとかえってわかりにくくなる。
awk を使えという指摘が的外れであるのは間違いない。
# gawk 3.0 以上のみに存在する gensub() を使えば可能
と思ったけど、ごめん。この場合は sed でも awk でもどっちでもいいや。 \1 なんて使う必要ないやんけ。 sed -e "/^#.*debian\.org.* ${sss}/s/^#//" -e "/^deb.*debian\.org.* ${aaa}/s/^/#/" /etc/apt/sources.tmp > /etc/apt/sources.list awk '/^#.*debian\.org.* '${sss}'/{print substr($0,2)} /^deb.*debian\.org.* '${aaa}'/{print "#" $0}' /etc/apt/sources.tmp > /etc/apt/sources.list 動作未確認。ダサ。
awk使えってのは単に\1とか使えないsedでも 大丈夫なようにってつもりだったんだが、>135 のやり方で良かったんだよな。 一回sedでとんでもないの書いて以来ちょっと 複雑になると条件反射でawkを持ち出してしまう・・・ 逝ってきます。 >133 嘘のようにきれいになったね。 一ヵ所だけ。引数チェックは[ "$#" = 1 ]だけでOK。
137 :
XP反対! :02/02/19 21:27
よろしくお願いします。 ppp="abc xyz" abc=123 xyz=789 for bbb in $aaa do echo $bbb #↑このechoコマンドで、123、789と出力するには、どうしたら? done exit 0 変数で入ってきた値を変数として、見られますか?
138 :
XP反対! :02/02/19 22:20
age
139 :
名無しさん@お腹いっぱい。 :02/02/19 23:52
wakarimasen
eval echo \$$bbb
>>140 よくわかったね... そういうことをやりたかったのか。
echo "123、789"
とか書いちゃうところだった予。
142 :
Win2K大好き :02/02/20 08:00
140さん ありがとうございます。 やってみます。
143 :
Win2K大好き :02/02/20 23:33
eval echo '$'$bbb これでできました。
144 :
名無しさん@お腹いっぱい。 :02/02/23 01:24
> #!/bin/sh > echo "aaa" | hoge | read VAL trash > echo "${VAL}" とやっても$VAL には何も入ってくれません。 これって > VAL=`echo "aaa" | hoge | gawk '{ORS="";print $1;exit}'` とかするしかないんでしょうか?
>144 hogeの出力を見せてん。
hoge ってゆーかぢつは md5sum なんだけど > 5c9597f3c8245907ea71a89d9d39d08e - こんなかんじ で、うしろの - はすてたいのである。
>146 うーむ、あまし関係なかった。shell variableの寿命の問題。 $ echo aaa - aaa - $ echo aaa -|read VAL trash; echo ${VAL} $ echo aaa -|(read VAL trash; echo ${VAL}) aaa $
>> 145 thx. しかし、その変数使っていろいろやりたいから そこで () でくくってしまうと面倒だな・・・
>148 while-do-doneでくくる手もあるYO。 $ echo aaa -|while read VAL trash; do echo $VAL; done aaa 嫌ならexportすれ。
>148 元はといえばGNU md5sumがものすごくださいのが原因なので、どこかから 別の実装のmd5(1)をもってきて使うとか、opensslを使うとか(openssl md5 < foo)、 してしまうのもいいかな。
>151 exportするのは一番最初に。環境変数は親shellには伝わらないよ。 #!/bin/sh export VAL
あ……忘れて……(w
とりあえず動くからチューニングきぼんぬ gdipc.plのshell版でdjbのtcpclient利用バージョン djbマンセーならenvdirで前半省略可 #!/bin/sh export DIP_SERVER=${DIP_SERVER:=example.com} export DIP_PORT=${DIP_PORT:=3495} export DIP_USER=${DIP_USER:=mydomain} export DIP_PASS=${DIP_PASS:=_md5_encoded_password_} export DIP_DOMAIN=${DIP_DOMAIN:=example.com} # export TCPCLIENT=${TCPCLIENT:=/usr/local/bin/tcpclient} export MD5SUM=${MD5SUM:=/usr/bin/md5sum} export AWK=${AWK:=/usr/local/bin/mawk} # case "$1" in 0|start|"") export ACTION=0 ;; 1|-r|stop) export ACTION=1 ;; *) echo "Usage: $0 start|stop" exit ;; esac # ${TCPCLIENT} -RHl0 -- "${DIP_SERVER}" "${DIP_PORT}" sh -c ' read SECRET <&6 echo "${SECRET}" DIGEST=`echo -n "${DIP_PASS}.${SECRET}" | ${MD5SUM} | ${AWK} "{ORS=\"\";print \\$1;exit}"` echo "${DIP_USER}:${DIGEST}:${DIP_DOMAIN}:${ACTION}" >&7 read RES <&6 case "${RES}" in 0) echo "Successfully";; 1) echo "Invalid login";; 2) echo "Offline request successful";; *) echo "Server did not respond:${RES}";; esac '
awkで環境変数を参照する方法ってありますか?
>155 はい。
157 :
名無しさん@お腹いっぱい。 :02/04/01 17:00
再利用
158 :
名無しさん@お腹いっぱい。 :02/04/04 23:04
シェルスクリプトで拾って、 #!/bin/sh awk -v PARA=$boke -f garuuu.awk とかじゃだめ?
awk 'BEGIN{print ENVIRON["HOME"]}'
160 :
名無しさん@お腹いっぱい。 :02/04/07 13:41
あれはあこがれるだけで十分。 乗ってみるとがっくりなスキーだったよ。オレンジ3S。
ごめん。誤爆した>160 ENVIRON[] は知らなかった。勉強になったよ。 メーカ製のWSとかに入っているgawkじゃないのでも使えるの?
>>161 gawkのドキュメントによるとPOSIX互換なら使えるらしい。
Solaris の場合、 /usr/bin/nawk, /usr/xpg4/bin/awk は使えたが、
/usr/bin/awk ではダメだった。
163 :
名無しさん@お腹いっぱい。 :02/05/01 23:30
質問を投げますので、答えを知ってる方名乗りあげろ。分かる方 は耳猫の女の子達との合コンにつれて行きます。 例えば1234567890という10個の数字が並んでいて、これを2と3の間、6と7の間、 9と0の間にコンマを付けたいとする場合(i.e. 12,3456,78,90)何かシェルスクリプト とかで自動的に出来る?結果的には縦一列に10桁の数字を沢山並べて、そのスクリプト を実行すると、全て左から同じ間隔でコンマが挿入されるような物。 DQNな俺に愛の手助けをプリーズ。
左から同じ間隔で、ってことは、2と3の間に挿入するんじゃなくて、 2桁目と3桁目の間ってことね。んじゃ、これでどうだ。 % sed 's/\(..\)\(....\)\(..\)\(..\)/\1,\2,\3,\4/' で、耳猫の女の子はどこ?
165 :
名無しさん@お腹いっぱい。 :02/05/02 00:03
すまん。これ、どーやって使うのだろうか・・・。 例えば $ cat /home/hoge/data 1234567890 2345678901 3456789012 みたいなファイルがあって、これをどーやって使えば 12,3456,78,90 23,4567,89,01 34,5678,90,12 みたいに変換出来るの?って質問だったんです。おせーて神様。
sed '長いので略' /home/hoge/data
167 :
名無しさん@お腹いっぱい。 :02/05/02 00:17
うおっ!!!!出来たyo。マジで出来ちゃった。うけけけ。 ありがとう!いやー、さすが数々のエキスパートが在中sしている2chは すごい。 今度新宿のコスプレバーで呑みましょう。そこに猫耳がいます。既に 合コンじゃないか。(w
遅くなったがようやくわかったぞ。 csh は COBOL-Shell ってことだな。
170 :
最近perlを使わなくなった男 :02/06/17 19:21
ほっしゅ、ほしゅ
171 :
名無しさん@お腹いっぱい。 :02/06/18 23:25
HP-UX 11.2 を使用しています。 下記の条件にあうようなシェルはどう書けばよいのでしょうか? (1) hoge というディレクトリ下にあるファイルで、タイムスタンプが 1998-2000年 の物を削除するシェル(ディレクトリにはいくつかの 階層がある)。 (2) 上記に加えて、「ディレクトリ名に .x が付くものは削除する」。 よろしく〜。
172 :
名無しさん@お腹いっぱい。 :02/06/18 23:30
>>171 わざわざスクリプトエンジンとしてのシェルを新規に設計するの?
/bin/shでは力不足ってこと?
174 :
名無しさん@お腹いっぱい。 :02/06/18 23:33
シェルスクリプト>172
176 :
名無しさん@お腹いっぱい。 :02/06/18 23:38
>>171 nxt というツールが高機能だと聞くから、簡単にできるかも。
177 :
名無しさん@お腹いっぱい。 :02/06/19 00:05
>>171 man find
くらいしか言うことないのよ、ほんとに
まさかエディタの使い方とか、マニュアルの見方まで分からないとはいわんよね?
今CSHをいじくっているのですが $2に何も入っていないかどうかを条件式で評価したいのですが 変数に何も入っていないときには、 記号か何かで表すと何が入っているのでしょうか? $2 = NULLとか$2 = " "等 やってみましたがまるでダメなのよね。
ありました。 $2 == ""
$2 == "" ありました
よその板でも書いたのですが、shの質問です。 $ echo "abc`echo def`" は abcdef となるのですが、 何故 $ str=`echo "abc \`echo def\`"` としなければ、同じ結果($str)が出ないのでしょうか? \ ← これってエスケープ文字で「`」がそのまま出てくるんじゃないですか? 最初に echo defが評価されるのはなんとなく理解出来るのですが、「`」が終息してないから? 基本的な事で申し訳ありませんが、宜しくお願いします
>>182 この場合、引用符の評価が二回行なわれるから、
二回目に評価して欲しいものは
\` みたいに書く必要がある。
var=`basename \`pwd\``
というのが典型例。
おお! さすが2ちゃんねる。 勉強させていただきました。 本当に有難う御座いました。
最近のシェルはネストできるように$()というのが使えるものも多い。 var=$(basename $(pwd))
>>185 $()が最初あって``が後からだと思うが。
>>186 Huh??
おぃ、誰かぁ〜突っ込んでやれ。
>>186 よーし、パパつこんちゃうぞ〜。
`` はもともとの sh (bourne shell) の機能。
$() は POSIX shell standard で `` よりあとから定義された機能。
>>186 が何と勘違いしていたのかの方が気になるな。
気になるな。
bashについて質問です。 チルダ展開をしたいのだけれども、hoge.datに u1001 u1002 u1003 ってな感じでユーザ名が入っているときに、 #!/usr/local/bin/bash -f for i in `cat hoge.dat` do echo ~$i done ってかいたら、チルダ展開してくれないんだけれども、 ものすごく勘違いしている? チルダ展開するようにするにはどうすればいい?
eval echo ~$i
リダイレクトの質問です。 $ ls -l 合計 0 -rw-rw-r-- 1 hoge hoge 0 Jun 27 18:37 aaa.txt $ ls -l aaa.txt bbb.txt > tmp 2>&1 2>&1 の所なんですけど、標準出力が tmp に入ってるのは理解できるのですが、 どういうカンジでエラーが tmp まで入ってるのですか? イメージ的には 出力が tmp まで入った後に、再度 2>&1 が評価されるってコト?? (最初の > tmpの部分で) Unix板の神様の皆様。 教えて下さい。
195 :
名無しさん@お腹いっぱい。 :02/06/27 18:58
>>194 このリダイレクトの文法、直観的には反対のように思いがちだけど、
コマンドラインはちゃんと左から右の順に1回だけ評価されてる。
> tmp のところで、ファイルディスクリプタ1に、
tmp というファイルが割り当てられ、
次に、2>&1 で、
ファイルディスクリプタ2に、
ファイルディスクリプタ1(tmpに割り当て済み)
が代入されるという感じ。
>>195 うーん。。ナルホド
有難うございます。
質問です。 $ cat filename abc cde efg $ while read ; do echo $REPLY ; done < filename ってした時に、どういう動きですか? 1, while がシェルを作る 2, read が変数入力待ち 3, done まで逝って、filename から読む 4, read が改行入るトコまで読み込み テキトーな変数に入力 5, しょーがねーから(出すものないから) echo する でアッテますか?
>>197 ちがうね。
1.(親)シェルがfilenameをオープンして、それを標準入力としてサブシェル(に相当するもの)を作る
2.サブシェルが whileループを実行する
3.ループ内の read では、標準入力から各ループごとに1行ずつ変数に読み込む
以上
あ、それから
>>197 のreadの引数が落ちてるね。
read REPLY と書きたかったのかな?
ありがとうございます
>>198 REPLY は抜けじゃないんです。何も書かなくても echo されるんです。
これってバグですか?
>>199 ほんとに cat 使ってる?
手で入力してない?
>>199 ふつう、read の引数がないとエラーになるはずだけど、
実装によってはOKの場合もあるのかな?
その場合でも、 filenameの行数分だけループするはずだから、
その回数だけ echo が実行されるはず。
ksh/bashではREPLYという特殊変数がある模様. readの引数がないとREPLYに代入される.
>>202 ありがとうございます。これで今日は良く寝れそうです。
204 :
名無しさん@お腹いっぱい。 :02/06/30 18:17
まずは UNIX & bourne shell だけで逝こう.と思いましたが, bash と sh の違いがわからず困っております. [ , ] が test の別名であることや,ヒアドキュメント等, 「自習テキスト」に載っていないものは bourne shell のものではないのですか? ぐぐってみても見つからず, % man sh しても bash のがでてくる始末. どう探せばよいかだけでも教えていただきたいのです. # 起動スクリプトも [ , ] ばっかり...Linux だから? # それとも個人の好み?
>>204 test = [ はもともと外部コマンドだったんだよ。
だから、シェル本体とは次元が違う問題になる。
とりあえず、
export name=var
や、
$(command)
は、
bash では使えるが、素のbourne shell では使えないので避けた方がよい。
>>204 ディストリに ash のパッケージない?
>>206 ash でも、
export name=var
や、
$(command)
が使えてしまうから困る。
>>205 > test = [ はもともと外部コマンドだったんだよ。
なんと.確かに /usr/bin に3つとも入っていますね.
> bash では使えるが、素のbourne shell では使えないので避けた方がよい。
これらも個人の好みだなんて思っていました...
>>207 > ash でも、
> export name=var
> や、
> $(command)
> が使えてしまうから困る。
うぅ,まとまったドキュメントが欲しいですね.
私は debian を使っておりますので,
bourne のみしか使えない環境になることはありませんが,
書くときにはこの辺のことを頭に入れておきたいものです.
210 :
名無しさん@お腹いっぱい。 :02/07/01 00:32
>>209 $() は POSIX で定められた機能だから、最近の UNIX なら
まず使えると思うけどね(商用 OS なら)。
ただ古い system でも動くようにしようと思うと、いろいろ
と使えなくなるから、SunOS4 の sh のマニュアルみて書い
たりしてるよ。
211 :
名無しさん@お腹いっぱい。 :02/07/01 00:38
>210 autoconfのマニュアルとか。 しかし最近のashは凄いね。set -o {emacs,vi}って何よ。
>>212 最近って。。。10年くらい前から使えたはず。
訂正.ヒアドキュメントは「自習テキスト」に載っています.ゴメソ.
215 :
名無しさん@お腹いっぱい。 :02/09/29 09:40
初心者です。ご存知の方いましたら、教えてください。 リモートシェルで環境変数を読み込んでからコマンドを実行したいっす! (例).profileを読み込んでからlsコマンドを実行します。 rsh -l usr ". .profile|ls" こんなのでいいでしょうか?
>>215 パイプ・・・?
;とか&&でできると思う。でも.profileなんか読み込んだらTERMが
設定されてないとか怒られるとおもうから.bashrcなんかに環境変数を書いとけば?
.bashrcはrshでも読み込まれるから。漏れはbashじゃないからよくわからんが。
ホットドックがいいですな。
219 :
名無しさん@お腹いっぱい。 :02/09/30 23:59
220 :
名無しさん@お腹いっぱい。 :02/10/01 19:19
forでループしてると、前回のコマンドが終了しないうちに 次のループに入ってしまい同じコマンドが実行されるようです。 これを防ぐ方法ありますか? または、ループの中で10秒くらいウエイトをかける方法ないでしょうか? シェルはkshでAIX5.1です
sleep 10
wait
223 :
名無しさん@お腹いっぱい。 :02/10/01 22:13
ありがとうございました waitでなぜかだめでしたので、 sleepでうまくいきました
224 :
名無しさん@お腹いっぱい。 :02/10/01 22:29
>>212 Autoconf のマニュアルいいよね。Shellology ってやつ。あれ大好き。
>>210 >
>>209 > $() は POSIX で定められた機能だから、最近の UNIX なら
> まず使えると思うけどね(商用 OS なら)。
% /usr/bin/sh
$ echo $(ls)
構文エラー: `(' unexpected
$ uname -a
SunOS void 5.9 Generic_112233-01 sun4u sparc SUNW,Ultra-5_10
% /bin/sh $ echo $(ls) 1.png 2.png 3.png $ uname -sr FreeBSD 4.7-RC
>>223 そ、それでいいのかよ。コマンドの実行が10秒以上かかったときはどうしてくれるのんだよ。
>>225 POSIX shは"/usr/xpg4/bin/sh"です.
標準出力に絶えず連続して、でてくる内容をファイルに保存したいんですけど(hoge > log)、 長時間出力させる必要があるので、1分ごとにファイルを分割させながら保存したいのです。 ですが、これでは最初のコピー先に書き込まれて分割できません。 hogeのプロセスは止めることができません。 どう書けばいいか教えて下さい。 #! /bin/csh set working_dir="/var/tmp" set run_time=720 #720min==12 hour cd $working_dir ( hoge > log )& while ($run_time) sleep 60 set dt=`date +%y_%m\-%d_%H:%M` set endfile = "$dt" cp log $endfile cp /dev/null log @ run_time-- end
>>229 logrotateとかnewsyslogのソースを探検してみるってのはどうよ。
しかしなぜに今時cshのシェルスクリプト。
231 :
名無しさん@お腹いっぱい。 :02/10/05 23:23
cshのスクリプトか・・・ BSDだからじゃないの?
ビーエスディーにはPOSIX準拠のシェルがハイッとります。
234 :
名無しさん@お腹いっぱい。 :02/10/06 02:43
うむ、awkなり、perlなりrubyなり通さないとダメかな? シグナル受けるとファイルclose&openするようなインターフェース になるかな? 外部フィルタを使うとすると。 案外、hogeがその機能持ってたりしてって、リダイレクトしてるのか。
>>229 cp /dev/null log
じゃなくって、
echo -n > log
とかだとどうなる?
>>234 そういうことしてくれるフィルタプログラムがあると便利そうだね。
hoge | foo /var/log/bar -t 60 とかすると、
自力で /var/log/bar.YYYYMMDDhhmm で rotate しつつ open&close して出力、
みたいな。
ていうか、実は既にあったりする?
>>237 daemontools にはそういうのをうまくやってくれる機能があるの?
>>238 >1分ごとにファイルを分割させながら保存したいのです
こんな機能ないよ。
>>239 loggerでsyslogに出力してnewsyslogする。
229です。 皆様レスありがとうございます。 logrotateで試して(kill -HUP使えるそうです)、 だめだったらperlでがんがってみます。
確か、newsyslogの設定ファイルに、pidファイル と、シグナル番号 を指定 すれば、newsyslogが宜しくやってくれたと思ったけど。 だから、syslog 経由しなくても、いいんじゃない。
>>236 Apache に付属している lotagelogs がそんな感じ。ちょっと仕様がダサいけど。
>>243 hogeがkill -HUPでログをクローズ・オープンし直してくれるのが確実ならね。
246 :
名無しさん@お腹いっぱい。 :02/10/12 22:46
シェルスクリプト程、とっつきやすくて究めにくいスクリプト言語も 無いだろうなあ。IFSとかエスケープの微妙な評価順とか、 いまだにうろ覚えだったり。そういう部分を使わないから、というのも 大きいが。
>>239 0.75以降だとALRMを送ると即ローテートするので、
1分ごとに svc -a すればいいんでないの?
248 :
名無しさん@お腹いっぱい。 :02/10/13 12:20
>>246 libtoolとかautoconfのスクリプト、./configure がうまくいかないときに見るんだけど、いつもめげる。
さげてみよう。
250 :
名無しさん@お腹いっぱい。 :02/11/03 22:45
初めてシェルスクリプトを書いたあんぽんたんですが教えてほしいことがあります。 pppの接続が勝手に切れた時に、自動で接続し直す(ついでにダイナミックDNSの更新もする)スクリプトのつもりで作りました。 hnup.plはDDNS更新用のスクリプトなので今回は無関係。 #!/bin/sh nowip=`ifconfig tun0 | grep inet | sed -e 's/.*inet //' | sed -e 's/ .*//'` if test "${nowip}" = "" then killall -TERM ppp sleep 5 ppp -ddial hoge sleep 2 nowip=`ifconfig tun0 | grep inet | sed -e 's/.*inet //' | sed -e 's/ .*//'` fi oldip=`cat /root/scripts/flets.ip` if test "${nowip}" != "${oldip}" then echo ${nowip} > /root/scripts/flets.ip /root/scripts/hnup.pl ${nowip} fi これでうまく行くと思ったんですが、どうもpppがシェルスクリプトの終了と同時に終了しているような気がするんですが、それを避けるにはどうしたらいいですか? これが気のせいだった場合は、もうひとつ疑問があります。 pppを起動してから実際に認証が成功してIPアドレスが割り当てられるまでに、瞬時〜3分程度のタイムラグがあるようなのです。 つまり起動してすぐにifconfig...とやっても当然アドレスが得られないのですがこれの回避策は、ipが表示されるまでループするぐらいしかないですか?
>>250 なぜppp.linkupとかppp.linkdownを使わないのでしょか。
(^^)
すいません。 おしえてください。 ある西暦年月日を変数に入れて・・・。 それを今日の西暦年月日と比較して 何日後?とかって、調べたりすることって できないですよね?
257 :
名無しさん@お腹いっぱい。 :03/02/16 02:49
254ではないが、簡単に日付のカウントをするって言うのはちょっと難しいな。 俺も悩んだ事はあるけど、月ごとに日付が変わるし閏年の問題も関わるので 暦に詳しくないとちょっと大変だ。俺はその点はあるコンピュータ言語を使って いたので解決できた。というのは言語に日付型というのがあったのでそれを利用 してインクリメントすれば良いだけだった。全ての処理を一から書く事と 比べれば簡単だ。
>251 スレ落ちしてるじゃん。
質問 コマンドのマニュアルがあってこれはmanのように一つのコマンドに対して ファイルとしてhelpみたいなのが書かれているのだけれど、これをHTMLに したい。ここで問題が発生しました。なんとファイル中にはシンボリックリンク が含まれているのです。シンボリックリンクさえなければsed,awkで簡単に ファイル名リストからhtmlに変換してテキストにhtmlのリンクを貼る事が出来ま す。でもシンボリックリンクがあるせいで上手くいきません。 どうしたら良いですか。
260 :
名無しさん@お腹いっぱい。 :03/02/16 06:25
意味不明 例示求む
>>259 ファイル中にシンボリックリンクは作れません
> なんとファイル中にはシンボリックリンクが なんとその「ファイル」はディレクトリである > ファイル名リストからhtmlに変換して 勿論この「ファイル名リスト」もディレクトリである だったりして:-P # sedで「簡単に」ディレクトリを読むことが出来るかどうかはしらんが # ls -l dir | awk ... かな?
>>257 月ごとの日にちは31,30,28が基本で、
閏年は/4の年に一度、100年に一度は無くて、400年に一度はあって…
ってDOSのTurboCでよくやってたなぁ
>>257 Epoch からの秒数に変換しちゃえばいいだけでは?
265 :
名無しさん@お腹いっぱい。 :03/02/16 13:04
>>264 閏秒でずれる罠。
秒までせずともJulian dayでいいと思う。
cat awk gawk@ というヘルプの書かれたテキストファイル(manのようなもの)があるとして、この gawkはawkへのシンボリックリンクになっているんです。ここで問題なのは、 例えばsambaを通したりするとgawk@が見えなくなってしまう事や、全てのファイルの操作、 例えばファイル内容を一部変えるとか他のフォーマットに変えるという事が シンボリックリンクがあると単純ではないなと。 ヘルプサイズを小さくするのにはシンボリックリンクは意味あると思いますが 保守しづらいなというのが感想なんですが、そこで私はtext->htmlに変換する所 でまずどうしようかと迷いました。perl/rubyを使っても良いのですが、シェル スクリプトか便利なコマンドがあるのかなと思って質問してみました。
>>267 まだわからん。
テキストファイルの中にシンボリックリンクは埋め込めないわけで、
ということはファイルをパースするラッパか何かがあるの?
そこら辺を説明してくれないとどうにも。
>>267 いろんなことがごっちゃに書いてあってなんだかわからん。
問題点を明確にせよ。
まさかと思うが html の href タグとシンボリックリンクを 同じものと思ってネーか?
271 :
名無しさん@お腹いっぱい。 :03/02/17 02:25
フォーマット変えるのなんてsymlinkかどうかなんて無視すればいいでしょ? symlinkであることを保存したい特別な理由があるならtestすればいいけど。 内容変更にしても2重に適用されてもへくらないようにしとけばsymlinkも無視できる。 ところで > sambaを通したりするとgawk@が見えなくなってしまう ってなに?
>>271 > > sambaを通したりするとgawk@が見えなくなってしまう
> ってなに?
ls -Fだとsymlinkが@でマークされるけど、SMBはsymlinkをサポートしないの
でマークされなくなるってことかなぁ。
だとすると、テキストファイルの中身云々とは完璧に無関係な話になってしま
うんだが。
>>267 説明能力が無い(というか良く理解してないからなんだろうけど)んだから、
人に分かってもらうには具体的に話すしかない。具体的に話せない事情は
あるのだろうが、そういう状態で
> があるとして
なんて勝手に要約したり例を捏造するから分からなくなる。
それはともかく、まあ以下のような解決策で済む話であろうと想像される
が違うか?
・個々のマニュアルページをhtml化する。他のマニュアルページへの
symlinkになっているものは不要。symlinkさえ作成する必要は無い。
・
>>267 の例で云えば、ハイパーリンクの部分は単に以下のようにする。
<a href="cat.html">cat</a>
<a href="awk.html">awk</a>
<a href="awk.html">gawk</a>
>268
いやだから、テキストファイル内にはシンボリックリンクはないのは分かっているん
ですけども。
要するに $ ls とした時に表示されるファイルリストを参照してこれを元に
htmlのインデクス作ろうかなと思ったんですよ。
そんだら、まったくこれがシンボリックリンク混ざってるもんだからイヤン
なわけです。
> があるとして
>なんて勝手に要約したり例を捏造するから分からなくなる。
要約してないでそのままなんでつが。
ブラウザでテキストファイル表示できますよね。それで
>・
>>267 の例で云えば、ハイパーリンクの部分は単に以下のようにする。
><a href="awk.html">gawk</a>
そうなんですけど、この時のファイルがシンボリックリンクだった場合の
処理がわからんのです。リンク元と先のリストはもしかしてls -l して
grepかなんかして、そのあと適当に行を抜き出してシンボリックリンクの
親を見つけて名前を置換する、ということになりますかね?
シンボリックリンクに対する操作が、lnという作るコマンドだけで他の操作
が無いので苦労してます。
275 :
名無しさん@お腹いっぱい。 :03/02/17 06:59
>>274 > シンボリックリンクに対する操作が、lnという作るコマンドだけで他の操作
> が無いので苦労してます。
symlinkかどうかなんて区別しないでやっちゃまずいのか?
<a href="cat.html">cat</a>
<a href="awk.html">awk</a>
<a href="gawk.html">gawk</a>
がだめな理由は?
>275 ><a href="gawk.html">gawk</a> >がだめな理由は? それだと、gawk@というテキストファイルへのリンクはUNIX内でなら可能だと 思うんですが、インターネットやWindowsなど他のファイルシステムに持っていく と問題が発生するようです。Perlなどのヘルプでmanみたいなものがあって、 printとprintf見たいな命令があったとして、これが一つのファイルに書かれてある。 printはシンボリックリンクでprintfは普通のファイルとなっているんですが、 このままでは他のコンピュータで扱う場合に問題が発生するので重複してても よいので普通のファイルとしてシンボリックリンクを変換しようかと。 数も/usr/binのファイル数くらいあるので手作業では出来ない。便利なコマンドが あるならそれを使えば良いかなと思っていたんですが。 仕事ではなくて趣味でやってるんですが、ああ、疲れた。もう寝ます。
277 :
名無しさん@お腹いっぱい。 :03/02/17 07:39
>>274 >要するに $ ls とした時に表示されるファイルリストを参照してこれを元に
>htmlのインデクス作ろうかなと思ったんですよ。
そんなことだろうと思ったが、そういう重要なことは最初に云え。
> リンク元と先のリストはもしかしてls -l してgrepかなんかして
別にそれでもよいが、
$ perl -e 'for (<*>) { printf("$_\t%s\n", readlink($_)); }'
でも試してみ。これはファイル名と(もしsymlinkなら)リンク先の名前を
タブ区切りのリストで出力するので、awkに喰わせて処理するには手頃だろう。
↑の*の部分はcshと同じglob(ワイルドカード)が使えるので、絞り込みたい
ファイル名に合わせて適当に。
>>259 おいおい、疲れた寝ますぅ?「お前らありがとう」は?
キミよー。文面からアレコレ勉強してそーつーのは分かるんだけど、
(すまんけどそれでベテランだったら目も当てられんのだけど)、
な〜んか用語の使い方っつーか、論理っつーかがズレてんだよね。
友達、同僚にもワカランとかクドイとか言われネーか?
素直に育てよ!
きっと % w3mman intro で済む話であろう。
>>276 > printはシンボリックリンクでprintfは普通のファイルとなっているんですが、
> このままでは他のコンピュータで扱う場合に問題が発生するので
どんな問題?
> 仕事ではなくて趣味でやってるんですが、
なんか関係あるの?
>>274 シェルスクリプトでやりたいなら test -L file とか test -h file で調べら
れる。
readlink(2)したいならreadlinkとかstatというコマンドがあるシステムもあ
るし、findのオプションで得られる場合もある。
>276 >gawk@というテキストファイルへのリンクはUNIX内でなら可能だと >思うんですが、インターネットやWindowsなど他のファイルシステムに持っていく >と問題が発生するようです。 全然分からん。「インターネットやWindowsにもってく」ってどーいう意味よ? 仮に「Webサーバ」だとして、サーバのOSは何よ? 大体、シェルスクリプト書いてるんでしょ? だとして、どうしてWindowsに持っていけるのか説明キボン 1.「HTMLファイルを出力する、シェルスクリプトを作ってる」 2.「lsで出力されたファイルへのリンク(Aタグ)を書くようなシェルスクリプトである」 3.「問題はシンボリックリンクされたファイルである(他のファイルは問題ない)」 4.「自分のUNIX内では動くが、Windows上やWebサーバ上では上手く動かない」 こーいう事か?
シンボリックリンクのファイルを除いてしまっていいのなら、 findで済む話だよな、、
>>282 > 4.「自分のUNIX内では動くが、Windows上やWebサーバ上では上手く動かない」
5.「だからリンクをsymlinkから実体のファイル名へ書き換えたい」
ということだと思われ。
285 :
名無しさん@お腹いっぱい。 :03/03/17 16:05
最近巷で人気の CodeRedII のログを grep してみたのですが、 IPアドレスの桁が不ぞろいで見づらいので以下のようにしてみました。 fgrep '" 400 ' /var/log/httpd-access.log| sed 's/ - -/>/g' | tr '>' '\t' | expand | cut -c -80 とりあえず見やすくはなったのですが、やり方がすごく馬鹿らしい気がします。 手馴れた人ならどうやるかぜひお聞かせください。
少なくともgrepとtrでできることはsedでできる。\tはTABを直接いれる。 sed '/" 400 /!d;s/ - -/\t/' /var/log/httpd-access.log | expand | cut -c -80
>>286 すいません、タブを直接入力ってどうやるんですか?
awk '$9==400{a=$1;$1="";print a "\t" substr($0,6,64)}' /var/log/httpd-access.log かなーりムリヤリ感が漂ってますが。
>>287 ttyやシェルの設定によるが、^V ^Iで入ることが多い。
290 :
名無しさん@お腹いっぱい。 :03/03/30 01:00
意外に簡単なようでかなりつまってしまいました・・・・・・お知恵拝借 dfコマンドにより /dev/hda3 14017872 1165268 12140524 9% / /dev/hda1 101089 18991 76879 20% /boot /dev/hda2 25197252 3353060 20564216 15% /home と出力されるのですが 15% /homeが90%になったときに警告を出したいことをしたいのですが (警告方法はecho "disk full"とか簡単にするつもり(cron等で動かすとして)) なにかいいヒントはございませんか?(´д`;)
"/home" で grep して cut したのを変数に代入して条件分岐でだめなの?
292 :
名無しさん@お腹いっぱい。 :03/03/30 13:21
290でつ… まさにそれです!dfにこだわる必要ないのね(w)ありがとうございました、やはり頭は柔らかくしておかないとダメポですね で、分岐はifでいいんすよね(ヲ
>>292 > で、分岐はifでいいんすよね(ヲ
んなことはやってみりゃすぐわかると思うが。
いや、df の結果を | で grep に渡して… ってつもりだったんだが、まあなんでもいいけど
295 :
名無しさん@お腹いっぱい。 :03/03/30 17:06
lsでもいいのでは?
??
297 :
名無しさん@お腹いっぱい。 :03/03/30 17:30
>>290 ちょっと本題とは違うけど、90% は一般ユーザにとっては
手後れでマズーだったような。
「dfで」90%と見えるうちはまだ大丈夫だったかと。
(^^)
∧_∧ ( ^^ )< ぬるぽ(^^)
302 :
名無しさん@お腹いっぱい。 :03/04/21 21:44
シェルスクリプトって perlやruby,pythonもはいるのそれならこんなスレ無用だな
>シェルスクリプトって >perlやruby,pythonもはいるのそれならこんなスレ無用だな マ板の頭が悪そうな発言スレに貼って来ていいですか?
304 :
名無しさん@お腹いっぱい。 :03/04/21 22:14
コマンド特有のスレ作れよ雑魚ども あと、sh,csh,bashとか固有のスレ作れよ、 zshはスレッドあるけどな。
>コマンド特有のスレ作れよ雑魚ども 「cutを使い倒すスレ」とか? マ板に「putsを使い倒すスレ」が立って、 「板違い。fprintfスレに逝け」とかレスが 付くようなもんだと思うが。 でも、それはそれで笑えるな。
306 :
名無しさん@お腹いっぱい。 :03/04/21 23:07
揚げ足はほんと人類の敵だな fprintfはプロブラム板に移動を御願いするがな
printfならここだな。
308 :
名無しさん@お腹いっぱい。 :03/04/21 23:13
もうUNIXにはうんざりだ学歴主義に毒された連中はUNIX使ってりゃイイよ 真の技術者は今を憂いの目で眺めている。
教えてください。 GWに停電があるんでサーバを止めないといけなくなりました。 会社行くのいやなんでshutdownをスケジュールにしたいんですが どういうスクリプトにすればよいんでしょうか?
>>309 スクリプトで時間稼がしてプチもいいのだが
Shutdown -h 時間とかあるんだが
長い時間に対応しなかったらナンだから
cronとかもあるし
古典的にリモート入ってでプチっと切るとか
つかさぁ
サーバって位だからUPSで勝手に切れると思うんだがどーよ?
むしろその辺の対策がないと本当の停電で困るよ
モレのは電源切れると勝手に落ちて電気くると勝手にあがる
というツワモノ
fsckはだいぶかかるようだがな(うひひ
>>310 UPSあるけど、その前に動作中のシステムを停止させる必要があります。
できればシステム終了が正常に済んでから電源断としたい。
システム終了のコマンドを投入し、「正常終了」のメッセージが出たら
shutdownのコマンドを発行したいのですが…。
ちなみにOSは、SYSTEM-Vです。
初心者な質問で申し訳ないが、cronでshutdownってできます?
roo権限ないと出来ないんでどうしようかと…。
>>311 UPS が shutdown してくんないの?
>>311 > ちなみにOSは、SYSTEM-Vです。
なんだ、ネタか。
system-vだとネタなの? 現役なのに…。
今時純粋なSysVなんてネタ以外には考えられんよなぁ。
>>311 crontabにはユーザを指定するフィールドがあるわけだが。
316 :
名無しさん@お腹いっぱい。 :03/04/28 17:51
質問なんですが… tcshのシェルスクリプトで、例えば「変数の内容について、最初の部分とパターンがマッチしたら、 最も短く一致する部分を取り除いた残りの部分を返す」のは、 ${var#pattern} では出来ないようなのですが、どういった方法で実現できるのでしょうか? いくらググっても出てきません…bashのはいっぱい出て来るのですが。
それは tcsh でシェルスクリプト書くなっていう先人のアドバイスです。
318 :
名無しさん@お腹いっぱい。 :03/04/29 12:47
afo_$1=hoge こんな感じに$1を変数afoの名前にくっつけて、値を代入したいんですが、 ./mona.sh: afo_引数=hoge: command not found となります。 どうすればできますか?
319 :
名無しさん@お腹いっぱい。 :03/04/29 13:00
/devをつかわずにサイズ0のファイルを作るにはどうすればよいですか?
:>
おねがい touch touch そこに touch あなたから touch
>325 うぅ、ただ歌いたかっただけじゃ! つーのはさておき「/devをつかわずに」って正確にはどういうことよ? ファイル作るッつーことは、絶対にディスクデバイスにアクセスする じゃんよ?脳内か?脳内なのか?!言うてみぃ! と言ってみるテスト
股間にtouch
>>326 アフォかお前。
マウントしてあるファイルシステムを通して利用するのに
いちいちデバイスのスペシャルファイルが要るとでも言うのかよ。
デバイスのスペシャルファイルがなくて どうやってファイルシステムをマウントするのだという話だと思うのだが。
問題からしてファイルシステムのマウントまで考えることを求めてないし
>>326 がそこまで考えているとも思えんが。
shで、 行数をカウントするにはどうすればよいのでしょうか? とりあえずwhile read 〜 expr でやっていますが、他にはどんな方法があるのでしょうか?
>>331 普通は外部コマンド (wc とか) におまかせするのでは?
というのでは答えになってない?
>>332 wcでできました。ありがとう御座いました。
こういう用途に使える外部コマンドが知りたかっただけなので
>>333 何かポケットリファレンスみたいなもの買ったら。
━―━―━―━―━―━―━―━―━[JR山崎駅(^^)]━―━―━―━―━―━―━―━―━―
/dev/randomから乱数を数字(文字列)として取り出す方法を教えてくれ。
od -N4 -td4 /dev/random | sed 's/.* //;q'
set output=`command` && echo "success" みたいに コマンドの出力を 変数に入れてかつ、そのコマンド終了コードを調べる事はできますか? 上のコードでは && が setに掛かるので、command が失敗した場合も 次の命令が実行されてしまいます。
FreeBSDではtcshになってしまっているのでcshとは違うかも知れないが、 %set hoge=`which ls` && echo "success ($?): $hoge" success (0): /bin/ls %set hoge=`which lss` && echo "success ($?): $hoge" %echo $? 1 となるわけだが。
ごめんなさい。csh では >340 のようになりました。 ただ、bash では、以下のようにうまく動かないんです(使いたいのは bash)。 ~$ hoge=`which ljs` && echo "success ($?): $hoge" ljs: Command not found. success (0):
bashのバージョンは? 2.05bはちゃんと動くぞ。
?
% sh
$ hoge=`which ls` && echo "success ($?): $hoge"
success (0): /bin/ls
$ hoge=`which lss` && echo "success ($?): $hoge"
$ echo $?
1
% bash
bash-2.04$ hoge=`which ls` && echo "success ($?): $hoge"
success (0): /bin/ls
bash-2.04$ hoge=`which lss` && echo "success ($?): $hoge"
bash-2.04$ echo $?
1
さすがに
>>338 の脳内bashの仕様はわからんな。
$ hoge=`which lss` && echo "success ($?): $hoge" lss: Command not found. success (0): $ echo $? 0 $ hoge=`cat lss` && echo "success ($?): $hoge" cat: lss: No such file or directory $ echo $? 1
>>345 そりゃbashじゃなくてwhichの方の問題だな。
type which
__∧_∧_ |( ^^ )| <寝るぽ(^^) |\⌒⌒⌒\ \ |⌒⌒⌒~| 山崎渉 ~ ̄ ̄ ̄ ̄
348 :
名無しさん@お腹いっぱい。 :03/07/19 14:45
1年前に買った入門UNIXシェルプログラミングをぜんぜん読んでない。
350 :
名無しさん@お腹いっぱい。 :03/08/02 00:52
おしえてください 以下のファイルがカレントディレクトリにある場合, @$ call_hoge.sh A$ hoge.sh `cat hogehoge` では出力が違ってしまいます.@でAと同じ出力を得るには call_hoge.shをどう変更すればよいですか? ---------hogehoge------------- hoge "" "ho ge" ------------------------------ -----------call_hoge.sh------- #!/bin/sh hoge.sh `cat hogehoge` ------------------------------ -----------hoge.sh------------ #!/bin/sh for i in "$@" do echo $i done ------------------------------
>>350 > call_hoge.shをどう変更すればよいですか?
どっちの出力にするんだって?
たぶんログインシェルが/bin/shと違うってことだろうが。
>>350 展開の順番と仕組みを勉強すると解るよ。
俺の O.S だと、man sh に詳しく書いてあったよ。
上の記事、忘れて。(^^;
あぼーん
355 :
名無しさん@お腹いっぱい。 :03/08/02 07:29
>>351 ログインシェルはkshです.
出力は@だと
-------------
hoge
""
"ho
ge"
-------------
に,Aだと
-------------
hoge
ho ge
-------------
になります.hoge.shへの引数が空白で区切られるのを
回避したいのですが.
356 :
((≡ ̄♀ ̄≡)) :03/08/02 07:45
>>355 未定義文字コードを使うな。どっちがどっちか分からん。
call_hoge.shの方を変えたいんなら、evalつけてみろ。
#!/bin/sh
eval ./hoge.sh `cat hogehoge`
358 :
名無しさん@お腹いっぱい。 :03/08/02 19:31
あまりにあんまりな質問なんですけど… #!/bin/sh cd /path/to/dir としてもスクリプトは新しいシェルで 実行されてしまうようで /path/to/dirに 移動してくれません。 このような場合どうしたら良いのでしょうか?
どうにもなりません。 かのnxtですら実装できなかった機能です。
え、そうなんですか? なにか大体手段はないでしょうか? 他のスクリプト言語ならできるとか…
あ、エイリアス以外で…
365 :
無料動画直リン :03/08/09 11:24
command.com か cmd.exe なら可能です。
エイリアス以外という事ならshell function
うまく行きました。ありがとう!
cshで、新窓開いてリモートマシンのファイルをtailした結果中の"*"が含まれた行を出力したいのですが、 ↓では何も出力されなくて困ってます(つД`) /usr/dt/bin/dtterm -e remsh XXX.XXX.XXX.XXX "tail -f /a/b/c.txt | grep \*" & 初歩的で申し訳ありませんが、ご教授御願いしまふ。。。
grep \* は grep "*" と同じ。ということは?
と、いう事はgrepまでで終わってしまっているという事ですか・・・。 "tail -f /a/b/c.txt | `grep *`" とすればいいのでしょうか?
echo "*" echo '*'
なるほど "tail -f /a/b/c.txt | grep '*'" ですか。 試してみます。どもです。
'tail|grep \\*'かな?
>>375 ありがとうございます。
試してみます!
>>370 試してみます、じゃなくて試した結果を書いた方がいいと思うが。
>>377 質問し、アドバイスを頂いておきながら結果報告が遅れて申し訳ありません。
<(_ _)>
明日、必ず結果を書きます。
'tail -f /a/b/c.txt | grep \\*' ダメでした。 dttermで窓が生成され、grepも生成されますが、何も表示されません。 リモート側でpsを見ると sh -c tail -f /a/b/c.txt | grep \\* となっているのですが・・・
> grepも生成されますが、何も表示されません。 grep \\* の結果としては実に順当だと思いまつが。
>>379 dtterm -e remsh XXX.XXX.XXX.XXX
のあとに、dttermで
tail -f /a/b/c.txt|grep \\\*
これでできますが、ひとつのコマンドでやる方法はわかりません。
fgrep使え。
あぼーん
あぼーん
>>380 報告が遅くなってすみません<(_ _)>
出力されない原因がわかりました。
tail -f | grep
としている為、パイプのストリームバッファの問題らしいです。
tail +0f | grep としたところ、先頭からある程度出力されて止まりました。
「tail結果の一部はパイプのせいでバッファ内に取り残されて出力されない」
という結果でした。
アドバイスありがとうございました。
パイプのバッファ(?)を0にする方法を調べてみます。
>>370 grepのバッファの問題なら、
grep 'RE'
の代わりに
sed -n '/RE/w /dev/fd/1'
って、してみれば。試してないから動くか分からんけど。
388 :
名無しさん@お腹いっぱい。 :03/09/15 16:24
あげ!
389 :
名無しさん@お腹いっぱい。 :03/09/24 17:30
bak2ファイルの内容 ----------------------------- #!/bin/sh TIME='date +%y%m%d' cp -r $1 $1.$TIME ----------------------------- # ./bak2 test.txt cp: copying multiple files, but last argument `+%y%m%d' is not a directory 詳しくは `cp --help' を実行して下さい. なぜ怒られるの?
TIME='date +%y%m%d' echo $1 $1.$TIME にして試してみ。
bak2ファイルの内容 -------------------------- #!/bin/sh TIME= 'date +%y%m%d' echo $1 $1.$TIME -------------------------- # ./bak2 test.txt ./bak2: date +%y%m%d: command not found test.txt test.txt.
やっぱネタだったか……
失礼 bak2ファイルの内容 -------------------------- #!/bin/sh TIME='date +%y%m%d' echo $1 $1.$TIME -------------------------- # ./bak2 test.txt test.txt test.txt.date +%y%m%d
TIME= 'date +%y%m%d' が間違ってるの?
date +%y%m%d の結果をTIME変数に入れるにはどうすれば?
シングルクオートじゃなくてバッククオートじゃないのか?
400!
perlのchopに相当するbuiltinって ありますか?
402 :
名無しさん@お腹いっぱい。 :03/10/04 03:49
age忘れ
>>401 builtin なんて大量にあるわけじゃないんだから
man で調べたらよかろう。
chomp相当が欲しいなら、そもそも要らないハズだが
UNIX何でも相談室(無料) OI2O-69-OI96
406 :
名無しさん@お腹いっぱい。 :03/10/08 20:52
質問です。 testコマンドの返り値を取得する事はできるのでしょうか? expr は $(expr 3 + 4)でできますよね? こんな具合にtestコマンドの返り値を取得したいのです。 もう一つ質問です。bashにはbool値があるのでしょうか? アドバイスよろしくお願いします。
$?
408 :
名無しさん@お腹いっぱい。 :03/10/10 20:19
shで 直接 command と起動するのと exec command と起動するのはどう違うのでしょうか? またビルトインコマンドを pwd と起動するのと builtin pwd と起動する場合の違いはなんでしょうか?
409 :
名無しさん@お腹いっぱい。 :03/10/10 20:21
(var=VARIABLE) とサブシェルで実行しているのに echo $var とすると VARIABLE と参照できてしまいます。何故でしょう?
既に定義されてたからじゃねーの? どのシェルの話よ。
>>408 シェルは親で,そこから起動されるコマンドは子供,という概念は良い?
親が待機していて,ユーザがコマンドを入力する度に子供プロセスを産んで
子供が終了したら再び親の待機 (シェルのプロンプト) に戻る.
もちろん親と各子供のプロセス番号は異なる.
exec つけたら,シェルの自分のプロセスをそのまま子供に渡す.
シェル上で (1) 普通に ls する場合 と (2) exec ls する場合とを比べる.
シェルの pid=100, ls の pid=101 として,表に見えるプロセスは
(1)
100
↓ (ls と打つ)
101 (100 は待機,ls の実行中)
↓ (ls 終了,プロンプトに戻る)
100
(2)
100
↓ (exec ls と打つ)
100 (シェルは自分のプロセス番号を ls に渡す.ls は pid 100 として実行される)
↓ (ls 終了,しかし戻るべきシェルはもういない)
死 (そのため,おそらくシェルを起動していた端末も閉じられる)
>>411 の続き.
ls の代わりに,自分のログインシェルと違うシェルで試してみるといいかも.
漏れの場合は,こんな感じ.
tcsh% echo $$
996
tcsh% bash
bash$ echo $$
1008
bash$ exit
exit
tcsh% echo $$
996
tcsh% exec bash
bash$ echo $$
996
bash$ exit
(端末が閉じる)
識者の皆様,
補足,訂正などよろしくお願いします.
>>408 execは自分自身が別のプログラムに置き換わるもの。
builtinの方は、組み込みコマンドを実行する場合は、差はない
組み込みと外部コマンドで同名があるときに、あえて組み込みを
実行させるためのもの。
>>409 ならない
よっしゃ、UNIXとシェルを平行して勉強するぞと力んだのはいいものの、 何を作っていいかがサッパリ。で、適当なunixコマンドをシェル関数で作ろう と思ったんだがなかなか難しいものでして。 manとかは頭が痛くなるので先の楽しみにとっておこ〜と思っても whoamiやwcを作る時点でもう悩む俺にアドバイス下さい。 オプションを抜きにすると、とりあえずどんな感じになるんでしょうか?
なんで whoami や wc なんだろう。
% cat wc.sh #!/bin/sh wc $*
414は「UNIXシェルプログラミング徹底解説」を読め。
http://store.nikkeibp.co.jp/item/contents/m_4822280489.html #!/bin/sh
whoami() {
echo $USER
}
wc-l_1 () {
i=0
while read l; do
i=`expr $i + 1`
done
echo $i
}
wc-l () {
t=0
nf=0
fmt='% 8d %s\n'
while [ $# -gt 0 ]; do
f="$1"
shift
nf=`expr $nf + 1`
n=`wc-l_1 < "$f"`
if [ $? = 0 ]; then
printf "$fmt" $n $f
t=`expr $t + $n`
fi
done
[ $nf -gt 1 ] && printf "$fmt" $t total
}
wc-l "$@"
>>415 いきなり複雑なのは難儀&思い浮かばなかったからです。良い例ありますか?
>>416 コマンドを模して作るのにその対象を使うのはご法度どす。
>>417 やっと行数(やや常識)とサイズ(かなりインチキ)が50行ほどでできたと
喜んでいたらそんなにシンプルに収まるのですか。
といっても動作の分からない部分が少々見受けられるので動かしつつ調べてみますね。
みなさんどうもッス。書店いってきます。
シェルでwcを書くなら
>>416 になるだろう。
Cで書くならともかく。
俺もリハビリに作ってみたが結構忘れてるな。 単語が数えられん・・・ 普通に標準コマンド盛り込めって話だがな。
while read l; do lines=`expr $l + 1` set -- $l words=`expr $words + $#` c=`expr "$line" : ".*"` chars=`expr $chars + $c` done キモの部分はこんな感じで。 BUGS ・行頭に空白文字があると read が無視しちゃって文字数がうまくカウントされない。 ・バックスラッシュが混じってるとやっぱりカウントがズレる。
× lines=`expr $l + 1` ○ lines=`expr $lines + 1`
できたました。多分えらい冗長な処理してるけどそれは初心者ということでご勘弁を。 さぁ次はナニをしたらいいのかしら。適当なお題くださいですの。(他力本願)
>>424 とりあえず、お題2つ。お好きなものからどうぞ。
1)sort の反対で、行単位でバラバラに並び替えるもの。
実行するたびに異なる出力結果になるものがほしいけど。
#C で書かれたbogosort ってのがある。
2)seq みたいに、連続したアルファベットを出力するもの。
$hoge f j
f
g
h
i
j
みたいなもの。a から fz まで とかみたいに、2桁とか 3桁でも出来ると便利。
できたら、大文字小文字を切替えるオプションとかも。
427 :
名無しさん@お腹いっぱい。 :03/11/21 23:15
リダイレクションした処理の中の変数を外でも使いたい場合はどうしたら良いのでしょうか? while read line do 略 done < $i つまり略の中で処理した変数を使いたいんです。 この前の処理でファイルの引数として $i使ってるので、この処理でexec使うと $iの内容が変わっちゃうんですよ…
429 :
名無しさん@お腹いっぱい。 :03/11/22 00:12
zshを、オンラインで解説したページでお薦めのがあれば教えてくれ。 英語でも構わんぞ。
>>427 > この前の処理でファイルの引数として
> $i使ってるので、この処理でexec使うと
> $iの内容が変わっちゃうんですよ…
この部分が意味不明。
exec < $i
で何で駄目なの?
431 :
名無しさん@お腹いっぱい。 :03/11/22 02:00
問題 Aに1〜9の乱数を1つ代入し Aが5以下であればage Aが6以上であればsage を表示するスクリプトを作りなさい
A=$[RANDOM % 9 + 1] if [ $A -lt 6 ]; then echo "age" else echo "sage" fi
% sh $ A=$[RANDOM % 9 + 1] %: not found $ exit 判定基準その1: 明示されてなければふつーsh。
「ふつー」ってのは「基準」なのか? 恥ずかしながら $RANDOM って知らなかった。勉強になりました。
判定基準その2: 明示されてなければスクリプトとして評価不能。
A=`date '+%S' | sed 's/[0-9]//'`
jotとかは禁じ手だよね、やっぱり?
>>438 1秒以内に何度も実行されたら同じ値になる。
A=`awk 'BEGIN{srand();print int(rand()*10)}'`
↑awk の srand() も同じ問題がある。
A=`expr $$ : ".*\(.\)"`
↑同一スクリプト中では実行するたびに同じ値になる。
A=`sh -c 'expr $$ : ".*\(.\)"'`
↑連続して実行すると連続した値になってしまう
A=`(head -1 /dev/random | od; echo + 10 % p) | dc`
↑/dev/random がない OS もある。
つーか宿題は自分でやれ、と。
>>426 その本読めば
>>425 とか簡単にできますか?
それとも、シェルスクリプトではなくて、
ちゃんとした言語で作れってことですか?
近くの書店にはその本無くて立ち読みも出来なかったんですけど。
>>441 適した道具を判断するのも頭の重要な使い方だと思うが。
A=`bash -c 'echo $[RANDOM % 9 + 1]'`
せっかくなので
>>432 さんのスクリプトに追記してみた
#!/bin/sh
A=$[RANDOM % 9 + 1]
if [ $A -lt 6 ]; then
echo "age":$A
else
echo "sage":$A
fi
変数Aが表示されるだけなんだけどけっこう重要かも
>>436 -lt の使い方の方が勉強になった…はじかちぃ〜
てっきり A<とかにするかと・・・・
自分とこの/bin/shの実体がbashなことも知らない犬ウザは犬板へカエレ!! しかもそれまでのレスを読むことすら満足にできない知障らしいし。 UNIX板へ来ずに犬板にスレ立ててそっちでやってくれよ。
>>445 < はリダイレクトを意味しちゃうからね
>>446 どうも話が変だと思ってたら、linuxしか使ったことのない人間が複数
混じってたというわけか。納得。
そういうのはlinux板でやってくださいね
>>446 Mac OS X でも /bin/sh は bash だったりして。
>>427 パイプでつないだらダメなの?
Cシェル使いはおらんのけ?
対話的には使ってもスクリプト書くのには使わない。
シェルスクリプトとはちょっと違う話かもしれませんが 引数をそのまんまsystem()ってやってるCのプログラムhogeに 「*」渡したら シェルスクリプトみたくファイル一覧に展開しやがりました。 system()もシェルと同じようにワイルドカードを展開するんですか? シェルはcshです。
シェルスクリプトは基本的にどこでも動くshで書いて、
(bourne) shで簡単に実現出来ないようなものならおとなしく
perlなりrubyなり使うな。
その意味、
>>442 の言ってることは正しい。
シェルスクリプトに向かないことをアクロバティックにshでやる必要なんて
どこにもないからね。
>>454 もし
% hoge *
とやってそうなったのなら、それはCでなくcshが展開したもの。
% hoge \*
とやれば望みの動作になるはず。
>>456 お返事Thxです。
ちと説明が足りなかったのですが、「"*"」を渡した時も同じですか?
>>458 Thx
ps見てたら/bin/sh -c ・・・ って出てたからなんだろなと思っていたけどこれか・・。
>>435 超遅レスだが
A=`expr $RANDOM % 9`
でイインジャネーノ?`
RANDOM: Undefined variable.
何度も出てるけど、ここはUNIX板。
標準のシェルがbashなのはlinuxだけの慣行なので。(
>>446 )
>>461 Linuxじゃなかったけど,良く見たら ksh だった。
/bin/sh だと $RANDOM なんてなかった。
逝ってきます...
463 :
名無しさん@お腹いっぱい。 :04/01/28 15:35
/bin/shで、スクリプトを作ってます。スクリプトの実行中、ユーザにファイル名の入力を求めるような部分が有るのですが。ここでファイル名補完をできるようにしたいです。どのような方法があるでしょうか? アドバイス願います。
質問するより、ファイル名を補完付きで一個入力させてそのまま返すコマンドを さくっと書いた方が早そうだが。どうせ補完自体はreadlineにさせるんだし。 そう思ってreadlineのサンプルを見ると、なにやらそれっぽいのがあるぞ。
一つおしえてください。 # ls |grep a1 01a1 02a1 # これらの表示を変数にしたいのですがどうしたら一番簡単でしょうか。 よろしくおねがいします。
>>464 そうですね。おぱかでした。
ありがとうございました。
>>465 > これらの表示を変数にしたいのですがどうしたら一番簡単でしょうか。
意味不明。
a1を変数で与えられるようにしたいのか、出力を変数に取り込みたいのか。
>>467 言葉が足りませんでした。出力を変数に取り込みたいのです。
ls |grep a1
01a1
02a1
A1-1=01a1
A1-2=02a1
こういう風に代入して、
cat $A1-1>>$A1-2;rm $A1-1
みたいな処理をしたいのです。
まともなシェルスクリプトの本なり web なり読めば 必ず載ってるはずだけどな。
シェル変数って-入れちゃだめだよな。
>>468 これじゃだめか?
set -- `ls|grep a1`
$1 -> 01a1
$2 -> 02a1
>>470 #!/bin/sh
set -- `ls|grep a1`
echo $1
echo $2
をつくって実行してみたところ、成功しました。この場合、シェル変数名に
こちらで好きな名前をつけるにはどうしたらいいのでしょうか。
「set シェルスクリプト」などでググっても見つからなかったので、
よろしかったら教えてください。
できまへん。適宜代入汁
またもや何をしたいのかわからんな。
UNIX板ってこんな雰囲気なの? なんかこわい。
>>474 まともな質問にはまともな答えが、
そうでなければそれなりの反応が返ってくるよ。
>>472 #!/bin/sh
set -- `ls|grep a1`
A1=$1
A2=$2
こういう風にすれば一応の目的は達成できました。
>>473 これをできる限り短く書きたかったのです。説明が下手でごめんなさい。
478 :
誰かこの問題といて :04/01/30 15:52
1)Write a script that asks for a file name. a)makes a backup of that file which is called file.back b)moves the original file to another directory. c)Prints the filename, owner, and size of the file.
宿題は宿題スレへ。 #!/bin/sh echo -n "enter file name: " read file cp -p "$file" "$file".back mkdir -p another mv "$file" another cd another ls -l "$file"
>>478 こっちの方がエレガント。
#!/bin/sh
another=${1:-/dev/null}
read -p "enter file name: " file; echo \
cp "$file" "$file".back
list=`ls -l "$file"`
if [ -d $another]; then mkdir $another; fi
mv "$file" $another
echo "$list"
> if [ -d $another]; then mkdir $another; fi 訂正。正しくはこっち。 if [ ! -d another ]; then mkdir another; fi
>>480 > read -p "enter file name: " file; echo \
> cp "$file" "$file".back
コピーせずにコマンドを表示するだけのような気がするが。
ログインシェルと起動シェルの違いは何ですか?
484 :
誰かこの問題といて :04/02/01 06:20
宿題スレが見つからなかったのでまたここに書き込みさせて下さい。 UNIX初心者です。ついでにPCも初心者です。 Write a script that prints out how many bytes are available on the disk (use df commands) and the % of the disk used. 479さん480サン ありがとうございました。助かりました。
>>484 仏の顔も三度までだぞ。
#!/bin/sh
echo "a script that prints out how many bytes are available on the disk
(use df commands) and the % of the disk used."
○○サンとカタカナで書かれると なぜだか「和田サン」を連想してしまう
488 :
名無しさん@お腹いっぱい。 :04/02/08 15:24
sed -n '1,$p' file.txt 1を変数にして値を変えていきたいんですけどエラーになってしまう。 ’ ’の中で変数は使えないのでしょうか?
使えません。
"$n",'$p'
この場合ならば tail +$num file.txt でいいけどな。
>488 ふつー sed -n "$x,\$p" file.txt マニアは p='$p' sed -n "$x,$p" file.txt >492 変数展開の抑制
> 変数展開の抑制 それは''と思われ
sed で改行って入れられるんだっけ?正規表現スレで聞いた方が早いかな?
シェルスクリプトからユーザーをログアウトさせることは可能でしょうか? シェルスクリプトにexitとか書いても実行されません。
killall -t `tty` -KILL OS 依存の上、ログアウトじゃねーし(w つーか無理。
499 :
誰かこの問題といて :04/02/18 00:24
Write a script that asks the user if you would like to create a file. If the user answers “yes”, then create a 0 byte file called fileone. If the user answers “no” then ask the user if you would like to print a file. If yes, ask for the name of the file to print and print the contents of the file. If no, exit the script.
echo a script that asks the user if you would like to create a file.\ If the user answers “yes”, then create a 0 byte file called fileone.\ If the user answers “no” then ask the user if you would like to print a file.\ If yes, ask for the name of the file to print and print the contents of the file.\ If no, exit the script.
宿題はクズカゴヘ
shとcshで % false | true と $ false | true で$?の値が違うんですがそーゆーもんですか? shの方でもcshと同じようになって欲しいんですが、どうしたらいいんでしょうか?
$ csh -c 'false | true'
目から鱗落ちまくり。
bashでディレクトリ中のjpgファイルをひろってHTMLでカタログを書き出すスクリプトを作っています. 出力イメージのサイズを引数で hoge.sh -1024x768 と指定出来るようにしました. このスクリプトで,与えられた引数が -[0-9]+x[0-9]+ になってるかどうか確かめたいのですが,何か方法がありますか? if [ $1 = -[0-9]+x[0-9]+ ] then ・・・ fi だと正規表現として判別してくれないので困ってます.ふぐぅ. 多分スゴイ厨な質問だとは思いますが,よろしくお願いします.
いきなり代入かよ。
if expr "x$1" : 'x\(-[0-9][0-9]*x[0-9][0-9]*$\)' > /dev/null then ... fi
>>507 出来ました.ありがとうございます.
出来たのですが,何をやってるのかわかりません.
良かったら参考になるページとか教えてもらえませんか?
まともな正規表現が使えて、無駄な出力をしないexprみたいなコマ ンドがあればいいのに、といつも思う。
まとも?なREと、むだな出力をしないとなると、 `echo $1 | perl -ne 'exit 1 unless /^-\d+x\d+$/'` むりくりこんなかんじ。
echo | egrep -s じゃダメかい。実装によっては egrep -q だったりするが。
急に仕事に必要になったので、 これからシェルスクリプトを勉強しようと思っています。 そこで、質問なのですが シェルスクリプトは、無限ループで 永続的に動かしたり(具体的には、HTTPDや FTPDをずっと監視して、それらの挙動によって スクリプトのifやcaseでFTPやHTTPに介入する等) 永続的に動かさないまでもなんらかのコマンドを 利用して定期的にスクリプトを起動したり、 シェルスクリプトを起動しながら、起動中に その都度、任意の他のアプリケーションや コマンドを手動で動かしたり出来るのでしょうか? Googleで「シェルスクリプト Redhat」で検索して、 シェルスクリプト解説サイトをいろいろ 見てみたのですが、そのところがどうしても載ってなくて…。 変な質問ですみませんが、よろしくお願いします。
>>515 即レスありがとうございます。
がんばってシェルスクリプト憶えます。
こりゃ(・∀・)イイ!! おもしろいですね
もしかしてできるわけねーだろ的な質問かも知れないけど、 手元でログインしているSolaris(A)から、 別室にあるSolaris(B)についてるモニタにdttermウィンドウを開く事って可能ですか? -help見ると-display displayname 接続するXサーバ とかいう一文があって、ここで指定するのかなと思って色々やっているんだけど... ちなみにやりたい事はSolaris(A)+Solaris(B)+Solaris(C)それぞれのディスク容量とかプロセスとかを 離れた所にあるSolaris(B)のモニタ上にgeometry指定で監視ツールの窓を並べてやるという感じなのだけど 全然うまくいかない ...俺ってもしかして実現不可能なことに必死に取り組んでる?(;´д⊂ヽ
ありゃ、スレ違いっすか.. 一応csh経由で #!/bin/csh (色々処理) dtterm〜〜 dtterm〜〜 dtterm〜〜 exit 0 とやるんでこっちに書いてみたんだけど
初めて作ったシェルスクリプトです。 分単位で指定するラーメンタイマーなんですがこのままだと表示が 180 179 . . といった具合にカウントダウンします。 それを180と出たら1秒後にそこが179、178と変わっていくタイプにしたくて echo $time の前に clear 入れてみたりしたんですけどターミナルの $PS1とかまで消えてしまうのです。こういった場合には何を使うのでしょうか? #!/bin/sh if [ $# -eq 0 ] then time=180 else time=`expr $1 \* 60` fi while [ $time -gt 0 ] do echo $time time=`expr $time - 1` sleep 1 done echo "完成!"
echo -n $time '\r'
>>526 ありがとうございました。
echoで対処できるとは思いもしませんでした。
ちなみに完成品はこんな感じです。
無駄が多いので改行多すぎになるためBASE64で。
----BEGIN BASE64----(timer)
IyEvYmluL3NoCgprYW89IiiOpaLPjqUpIMS0zf3D5iEhIgpnYXVnZV9tYXg9MjAK
Z2F1Z2VfemFuPSRnYXVnZV9tYXgKZ2F1Z2Vfa2FuPTAKbG9vcF9jb3VudD0wCgpj
YXNlICQjIGluCiAgICAwICkgdGltZV9tPTMKCXRpbWVfcz0wOzsKICAgIDEgKSB0
aW1lX209JDEKCXRpbWVfcz0wOzsKICAgIDIgKSB0aW1lX209JDEKCXRpbWVfcz0k
Mjs7ICAgIAplc2FjCgpnYXVnZV9zcGVlZD1gZXhwciBcKCAkdGltZV9tIFwqIDYw
ICsgJHRpbWVfcyBcKSAvICRnYXVnZV9tYXhgCgppZiBbICR0aW1lX20gLWx0IDEw
IF07CnRoZW4KICAgIHRpbWVfbT0wJHRpbWVfbQpmaQppZiBbICR0aW1lX3MgLWx0
IDEwIF07CnRoZW4KICAgIHRpbWVfcz0wJHRpbWVfcwpmaQoKI3doaWxlIFsgJHRp
bWVfbSAtZ3QgMCAmJiAkdGltZV9zIC1ndCAwIF0Kd2hpbGUgWyBgZXhwciAkdGlt
ZV9tICsgJHRpbWVfc2AgLW5lIDAgXQpkbwogIGVjaG8gLWUgIiR0aW1lX206JHRp
bWVfcyBbYCBmb3IgaSBpbiBcYHNlcSAxICRnYXVnZV9rYW5cYCA7IGRvIGVjaG8g
XCMgOyBkb25lIHwgdHIgLWQgIlxuIiBgYCBmb3IgaSBpbiBcYHNlcSAxICRnYXVn
ZV96YW5cYCA7IGRvIGVjaG8gLSA7IGRvbmUgfCB0ciAtZCAiXG4iIGBdICRrYW8g
XHJcYyIKCiAgbG9vcF9jb3VudD1gZXhwciAkbG9vcF9jb3VudCArIDFgCiAgaWYg
WyAkbG9vcF9jb3VudCAtZXEgJGdhdWdlX3NwZWVkIF0KICAgIHRoZW4KICAgICAg
bG9vcF9jb3VudD0wCiAgICAgIGdhdWdlX3phbj1gZXhwciAkZ2F1Z2VfemFuIC0g
MWAKICBmaQogIGdhdWdlX2thbj1gZXhwciAkZ2F1Z2VfbWF4IC0gJGdhdWdlX3ph
bmAKCiAgdGltZV9zPWBleHByICR0aW1lX3MgLSAxYAogIGNhc2UgJHRpbWVfcyBp
bgogICAgICAtMSApCiAgICAgIHRpbWVfcz01OQogICAgICB0aW1lX209YGV4cHIg JHRpbWVfbSAtIDFgCiAgICAgIGlmIFsgJHRpbWVfbSAtbHQgMTAgXQoJICB0aGVu CgkgIHRpbWVfbT0wJHRpbWVfbQogICAgICBmaSA7OwogICAgICBbMC05XSApIHRp bWVfcz0wJHRpbWVfcyA7OwogIGVzYWMKCiAgY2FzZSAka2FvIGluCiAgICAgICIo os+OpSApIMS0zf3D5iEhIiApIGthbz0iKI6los+OpSkgxLTN/cPmISEiOzsKICAg ICAgIiiOpaLPjqUpIMS0zf3D5iEhIiApIGthbz0iKCCOpaLPKSDEtM39w+YhISI7 OwogICAgICAiKCCOpaLPKSDEtM39w+YhISIgKSBrYW89IiggICCOpSkgxLTN/cPm ISEiOzsKICAgICAgIiggICCOpSkgxLTN/cPmISEiICkga2FvPSIoICAgICkgxLTN /cPmISEiOzsKICAgICAgIiggICAgKSDEtM39w+YhISIgKSBrYW89IiiOpSAgICkg xLTN/cPmISEiOzsKICAgICAgIiiOpSAgICkgxLTN/cPmISEiICkga2FvPSIoos+O pSApIMS0zf3D5iEhIjs7CiAgZXNhYwoKICBzbGVlcCAxCmRvbmUKCmVjaG8gIiR0 aW1lX206JHRpbWVfcyBbYCBmb3IgaSBpbiBcYHNlcSAxICRnYXVnZV9tYXhcYCA7 IGRvIGVjaG8gXCMgOyBkb25lIHwgdHIgLWQgIlxuIiBgXSAojt+iz47fKSClx6Wt pb8hISIKYmVlcCAtZiAzMDAuNyAtciAyIC1kIDEwMCAtbCA0MDAKCg== ----END BASE64----
質問です Cシェルスクリプト上でrshを使用して他サーバでの処理をする部分で悩んでいます 自分ではいくつかのサーバを巡回して各サーバの/devel/bataにある古い バックアップファイル(*.bak)を削除してまわるスクリプト(のつもり)なのですが、 実際に走らせてみたところ、最初のalfaにrshした後、 ローカルコンソールにターミナルが開いて入力待ちという状態になってしまいます。 しかもログアウトでrshを抜けたら今度はローカルの/devel/bataを見に行っちゃうし… (その動作自体はちょっと考えてみれば至極当然の動作なのだけど…) こういう場合に、rshで停止せず、rsh接続のままで以降の処理に進ませたい場合には どんな風にスクリプトを組んでいけばいいのでしょうか? スクリプトに詳しい方よろしくお願いします。 環境は全マシンともSolaris8です #!/bin/csh #処理サーバ名:alfa bravo charlie delta set Tgt_Server="alfa bravo charlie delta" # foreach SV (${Tgt_Server}) rsh ${SV} cd /devel/bata foreach file ( `find . -mtime +5 -type f -print` ) echo $file | grep ".bak" >& /dev/null if ( $status == 0 ) then echo "exist" $file >& /dev/null rm $file endif end end exit 0
>>529 #!/bin/csh
cd /devel/bata
foreach file ( `find . -mtime +5 -type f -print` )
echo $file | grep ".bak" >& /dev/null
if ( $status == 0 ) then
echo "exist" $file >& /dev/null
rm $file
endif
end
この部分を別のファイルにする。
#!/bin/csh
#処理サーバ名:alfa bravo charlie delta
set Tgt_Server="alfa bravo charlie delta"
#
foreach SV (${Tgt_Server})
rsh ${SV} 上のファイル
end
exit 0
rshの引数に分けたファイルを指定すればいい。
>>530 レスどうもです。
別ファイルにできればいいのですが、
業務用に納入まで実環境を保持するとか何とかいうサーバもあって、
そういうサーバだとこんな細かいファイルでさえ「入れたい」と言うと非常にイヤ〜な顔されるのです…
しかもそれに関してのグチが自分にじゃなく、自分の上の者にいって、上からこっちに来るのが精神的にキツイというか(´д`υ
なのでローカルサーバからリモートで出来るようなら
それにこしたことがないのです。
rshやrloginでは実現不能なのでしょうか?
いまどきsshじゃなくてrshつかうの? ま、どちらにしても、 rsh remotehost /bin/sh -c 'あとはずらずらshスクリプト' ってやれば?
>>527 くるくるしてるのが(・∀・)イイ!! ↓コレ
02:47 [#-------------------] ( ・∀) 調理中!!
>>533 % uudecode timer.b64
% No `begin' line Σ(´Д`lll) エエエエー
コピペで解凍でけたの?
>>534 コピペしてない、navi2chユーザーだから
M-x navi2ch-base64-write-region
でしますた。ちなみに今uudecodeしたら
uudecode: txt: No `begin' line
と同じメッセージがでました。
uuencodeはbase64とちがうだろ b64decodeってのものある場合があるが
シェルスクリプトから、ファイルのタイプスタンプを取得するのって、 みなさんどうやってるのでしょうか? set `ls -al` とか使おうとしても、AIXだと古いファイルは日時部が 年号になってたりして、うまくいきません。(時分秒まで欲しいのです) タイプスタンプを取れるコマンドとかあるのでしょうか?
tcsh -cf 'filetest -M: filename'
tcsh入ってないみたいなんです、ごめんなさい。。
sh系ならこんな感じ。perlぐらいいれとけよ。 a=/kernel; b=`perl -e "@s=stat('$a');print \\$s[9];"`; echo $b
>>538 Linux で bash だけど。
find コマンド使えば、-printf で書式指定できる。
find . -maxdepth 1 -printf "%p %CY%Am%Ad%AH%AM%AS\n" とか。
/dev/nullとdiff -acなりdiff -auしてhead -1する。 空のファイルが相手なら何か適当に別のファイルとdiff
>>541 >>543 perlは入ってるんですが、statが入っていませんでした。ごめんなさい。
>>542 AIXのfindでは-printfオプションが存在しないみたいです。ごめんなさい。
>>544 この方法だと取得できました。ありがとうございます。
diffの入ってないマシンは考えにくいので、↓こんな感じでやることにしました。 #!/usr/bin/ksh set -- `diff -c $1 /dev/null | head -1 | sed 's/^\*\*\* //'` fstmp=$6 # yyyy取得 case $3 in # mm 取得 Jan) fstmp=${fstmp}01;; Feb) fstmp=${fstmp}02;; Mar) fstmp=${fstmp}03;; Apr) fstmp=${fstmp}04;; May) fstmp=${fstmp}05;; Jun) fstmp=${fstmp}06;; Jul) fstmp=${fstmp}07;; Aug) fstmp=${fstmp}08;; Sep) fstmp=${fstmp}09;; Oct) fstmp=${fstmp}10;; Nov) fstmp=${fstmp}11;; Dec) fstmp=${fstmp}12;; esac if [ $4 -lt 10 ]; then # dd 取得 ただし1桁なら0補完 fstmp=${fstmp}0 fi fstmp=$fstmp$4`expr substr $5 1 2``expr substr $5 4 2``expr substr $5 7 2` echo $fstmp
head -1 | sed '...' は sed -e '...' -e 2q とひとつにまとめてしまいたい。
01.mp3 から 10.mp3までのファイルがあるとして for i in *.mp3 do echo $i done というスクリプトを走らせると1から10まで表示されるのですが for i in $1 do echo $i done にして引数に*.mp3をつけて実行しても01.mp3としか表示されません。 なぜこのようになるのでしょうか? for文に引数の値を持ってくることはできないのでしょうか?
*.mp3 は一つの引数じゃなくて、展開されてから渡される。 $1の代わりに、for i in "$@" 使え。
>>550 ありがとうございました。ちなみに作ったものはこんな感じです。
持っているmp3プレーヤーがid3tagを英字でしか表示できないのでローマ字に変換するスクリプトです。
id3infoの情報をgrepやsedを使って削るという非常に汚い処理ですが。
#!/bin/sh
if [ $# -eq 0 ]
then
file=*.mp3
else
file=$@
fi
for i in $file
do
id3ed -s `id3info $i |grep TIT2 |sed s/'=== TIT2 (Title\/songname\/content description): '//g |kakasi -Ha -Ka -Ja -Ea -ka |sed s/' '/^/g` -S $i
done
>>550 それって、for i と等価じゃなかった?
>>551 ファイル名に空白とか入ってる可能性があるから、"$@" にしろと言ったのに、
わざわざ別の変数に入れたりしたら台無し。
>>552 そうかもしれんが、ここで省略法を教えても教育的でない。
>>550 だって教育的とは言えんだろ。説明してないこと大杉。
>>554 引数の使い方に関するチュートリアル全部書けってか
>>553 それなら$@を他の変数に入れずに引数がなにもない場合に
*.mp3を指定したことにするにはどうしたらよいのでしょうか?
こうかな #!/bin/sh case $# in 0) set *.mp3 ;; esac # if [ $# -eq 0 ]; then set *.mp3; fi でも可だが。 for i in "$@"; do ごにょごにょ "$i" # $i じゃなく "$i" done
>>555 全部書けというより、
>>550 では話が繋がってないだろ。
シェルではワイルドカードは展開してあとのものがプログラムに渡される
↓
$1では最初の一つしかとれない
↓
すべての引数を舐める必要がある
「全部書」きたくなけりゃ、なおさらここで
すべての引数を舐めるには
for i
do
...
done
を使う、とするのが一つの落としどころだろ。
"$@"まで持っていこうとするとさらに $*, $@, quoteと変数展開, "$@" を順に説明することになる。
"$@"自体は一目で疑問なく理解できにくいと思うし。
560 :
名無しさん@お腹いっぱい。 :04/05/06 20:54
初心者なんですけど、 nkfとplatexを続けて実行するシェルスクリプトを作ってみたのですが、 次のようなエラーが出てうまく実行できません。 ./nkfplatex: line 5: syntax error near unexpected token `then' ./nkfplatex: line 5: `if[ $1 = $bname ]; then' すみませんが、どこが間違っているのか教えて頂きたいのですけど…よろしくお願いします。 #!/bin/bash bname=`basename $1 .tex` if[ $1 = $bname ]; then echo "texファイルではありません" else nkf -w $1 > tmp.tex platex tmp.tex mv tmp.dvi $bname.dvi rm tmp.* fi
>>561 お〜、なんと馬鹿な事を聞いてしまいましたね。
ありがとうございました。
>>560 if [ "$1" = "$bname" ]; then
みたいに"でくくる習慣をつけた方がいいよ.
こういうののデバッグははまるから.
もっというと、-で始まっても大丈夫なように、x"$1" とかにする。
SSHでリモートフォワーディングを常に行いたいので、切断しても再接続する ように #!/bin/sh trap 'exit 1' 0 2 3 9 15 while true do ssh -R ポートA:localhost:ポートB sshホスト sleep 15 done というスクリプトを常に実行しているのですが、たまに Warning: remote port forwarding failed for listen port ポートB というメッセージが出て、リモートポートフォワーディングに失敗する時が あります。こういう場合は、大抵サーバー側にポートBをLISTENしているsshdが 残ってしまっているので、このメッセージを検知したらsshを通してサーバー 側で $ sudo fuser -k -n tcp 5903 というコマンドを実行したいのですが、どのように実現したらいいでしょうか?
566 :
名無しさん@お腹いっぱい。 :04/05/28 11:46
Perlみたいに for i in ((1..10));do echo $i;done こんな感じのことできないですかね。 for i in $(seq 1 10);do echo $i;done for((i=1;i<=10;i++));do echo $i;done とするしかないのかな? あと、 $ A=B echo $A というのが思ったように行きません。これはどうしてなのでしょうか? $ A=B; echo $A とすれば表示はされますが、今度はログインシェルのシェル変数として ごみが残ってしまいます。
>>566 zshなら {1..10}
A=B echo $A
は、echoプロセス(または内部コマンド)の環境変数としてAを設定するんであって、
それを解釈するシェルの変数が変化するわけじゃない。
A=B prinetnv A
と比較し、誰が getenv(3) してるか理解せよ。
A=B sh -c 'echo $A'
>>567-568 ありがとうございます。
>A=B echo $A
>echoプロセス(または内部コマンド)の環境変数としてAを設定するんであって、
>それを解釈するシェルの変数が変化するわけじゃない。
ということは、$Aを展開しているのはログインシェルであって、
echoは与えられた文字列をただ出力するだけだから、この例だと、
$Aはログインシェル上では空なので、echoには何の値も行き渡って
ないということですか。なるほど。
ログインシェル上で一般に
VAR1=AAA VAR2=BBB command (とくにCC=gcc makeやLANG=C command)
というものをよく見かけますが、これはそこ、つまりログインシェルから
起動される子プロセスに限定された環境変数の設定ということですか。
"VAR1=AAA VAR2=BBB command"という文字列を受け取り、VAR1=AAA VAR2=BBB
という部分は、子プロセス起動のための値設定という風に解釈されるのですね。
なるほど。勉強になりました。
補足ですが、このことは以前も悩んでいたのですが、 その時は"VAR=AAA command"という一文が以下のように解釈されると誤解してました。 % VAR=AAA; command; unset VAR つまり、"VAR=AAA command"という一文を実行している間だけ、ログインシェル自体の 環境変数を弄くってるものだと、大きな勘違いをしていました。
571 :
名無しさん@お腹いっぱい。 :04/05/30 20:42
ちょいと教えてください
朝、Cronタイマーで
% mpg123
http://64.236.34.196:80/stream/1018 &
と、起動するのですが停止はいつも ps ax でみて kill で止めます。
Cronで自動的に止めるには何かいい書き方ないですか?
まぁ早く起きてコンソール打たないといけないからいい目覚ましではあるのですがw
>>571 OS が何か知らないけど、killall は?
$$
すたーと
#!/bin/sh
mpg123
http://64.236.34.196:80/stream/1018 &
echo $! > /var/run/mpg123.pid
すとっぷ
#!/bin/sh
test -f /var/run/mpg123.pid && kill `cat /var/run/mpg123.pid` && rm /var/run/mpg123.pid
>>572 犬 赤帽9です
>>573 もうすこしヒントを…
>>574 ありがとうございます、できました、pidファイルで操作するというのはこーいうことでしたか
とても勉強になりました
これでジワジワと音量を上げてみるスクリプトに移行できそうですw
(aumix使います)
576 :
名無しさん@お腹いっぱい。 :04/05/31 23:48
MP3ラジオ目覚ましスクリプトw
#!/bin/sh
#vol set
aumix -v 0
#Start music
mpg123
http://64.236.34.196:80/stream/1018 echo $! > /var/run/mpg123.pid
#aumix contorol
echo "Wake Up?"
/usr/bin/aumix -v 20
sleep 60
/usr/bin/aumix -v 40
echo "Wake up!!!"
sleep 60
/usr/bin/aumix -v 60
sleep 60
/usr/bin/aumix -v 80
echo "Good morning!!"
#Stop music
sleep 1800
test -f /var/run/mpg123.pid && kill `cat /var/run/mpg123.pid` && rm -rf /var/run/mpg123.pid &
ってなことで1分おきにリダンダントボリュームの鯖目覚ましアラームができますた。
こんな生ぬるい曲で起きられるかタコがぁ!!とおっしゃるのでしたら
http://64.236.34.97:80/stream/1003 などどぞ〜 詳しくはwww.shoutcast.com
>>574 感謝!!_| ̄|○
なんか鳴らなくねぇか?
おすすめのBASH本ありますか? 小生UNIXはあまりなれてなくて, なおかつシェルスクリプトをがんがん書かなければならないようになりぁmした。
bash独自の機能なんて普通使わない
zshマンセー! いやbash使いだけどな
>>579 bashに限らずシェルスクリプト全般の本だろうね。
漏れにはおライリーしか思いつかんが
ピアソンにsed,awk,sh,csh,bashの詰め合わせセットみたいな本なかったか? あれくらいが丁度いいのかも。
autoconf が作る configure とかを読み進めていくと 結構勉強できると思う。
585 :
名無しさん@お腹いっぱい。 :04/06/06 00:13
&heart;
&hearts;
587 :
名無しさん@お腹いっぱい。 :04/06/09 21:07
$ cat hoge alias integer='declare -i ' integer n=1 n=$n+1 echo $n $ ./hoge ./hoge: integer: command not found +1 サブシェルの中でエイリアスは出来ないんですね。
親からひきつがれるのは環境変数だけ
普通エイリアスなんてものはrcファイルに書くから引き継ぐ必要は ないと思う。
588のせいで論点を勘違いした。
>>587 の使ってるシェルが何かわからないが、
man bashによると
>シェルが対話的でない時には、 shopt コマンドによって
>expand_aliases オプショ ンが設定されていない場合に限り、エイリアスの展開は行われません
>>590 ありがとうございます。スクリプトの中に
shopt -s expand_aliases
を先頭に追加して
$ ./hoge とすると
2
と表示され、エイリアス展開が行われているようです。
man bash を読み込んでなかった自分が恥ずかしい・・・
スクリプト中でalias使うなよ。
593 :
名無しさん@お腹いっぱい。 :04/06/11 02:35
すいません質問です。 ListFileの中にファイル名が行方向に 並んでるとしてKシェルだと #!/bin/ksh while read -r filemei do cat $filemei done < ListFile こんな感じでそのリストの中のファイル名のファイルを みれると思うんですが・・・・ これをCシェルで作るにはどうすればいいのでしょうか? (このスレを読んでCシェルで作るのは馬鹿だというのは 十分理解しましたが・・Cシェルで統一だそうで・・お願いします)
awk '{print $1}' filemei | xargs cat とか。 でも、csh に統一とかいうアホな状況は変えた方がいいよ。 (例えばその会社を辞めるとか…(ぉ)
あ、間違えた。 awk '{print $1}' ListFile | xargs cat だた。 でも単に cat `cat ListFile` でいい気もするな。 あるいは ListFile の中身がでかいなら xargs cat <ListFile とか。
596 :
名無しさん@お腹いっぱい。 :04/06/11 07:23
>>594 ,595
ありがとうございます!!
xargs cat <ListFile はいいですね。
って・・例えばリストが
aaa
bbb
なら cat aaa bbbと打つことと同じになるんですよね?
cat aaa
cat bbb
としたいんですが・・一緒なんですかね?
実際はcatじゃないのですが
どのコマンドでもこの方法は使えるのかな
引数でファイルを複数指定できないコマンドならだめなんですかね
>例えばその会社を辞めるとか
いや・・・また新人で今月配属になったばっかりなんで
そんなこと言わないで〜〜〜〜
> 引数でファイルを複数指定できないコマンドならだめなんですかね せっかく xargs っていうコマンドがあるってことが分かったんだから、 人に聞いてばかりいないで、マニュアル読んでみようぜ。 答はマニュアルに書いてある。
foreach i (`cat filename`) どうしたこうした end cshは知らないが、大体こんな感じか?
>597 ありがとうございます。 ですよね・・・一に勉強二に勉強ですね >598 ありがとうございます。 参考にさせていただきます。
#!/bin/sh filename=dat_`date +%Y%m%d_%H%M%S`.bz2 tar jcvf $filename ./dat/* > /dev/null というシェルスクリプトをcrontabに登録しているのですが, ここでできるtar.bz2をSTDOUTに出すにはどうしたらいいのでしょうか tar --helpしていろいろやってみたのですができませんでした。 よろしくお願いします。
cat $filename といじめたいところだが、 tar jcvf - ./dat/* のことか?
>>601 基本的な質問に回答ありがとうございます。
そういえばImageMagickでも芳醇出力に出すときにファイル名があるべきところに -
を入れるというオプションがありました。
これって,Unixの世界の約束事なんでしょうか。
ええ、わりと。駄目な時は/dev/stdoutで。
/bin/shって>>のときO_APPENDしてくれないの? ログファイルを切り詰めたら穴があくんだけど。
openしっぱなしのファイルを縮めたってこと?
bash のスクリプトで、 実行結果の文字列を、標準出力ではなく、 コマンドラインにセットすることはできますか?
xargs ?
xargs、さっそく調べて見ましたが、 自分の考えていたのとは違う感じでした。 補足すると、実行したいわけではなく、 キー入力した感じにしたいのです。 ---標準出力にした場合--- $ xxx ←シェル実行 hello ←結果文字列 $ ------- ---やりたいこと--- $ xxx ←シェル実行 $ hello ←結果文字列をここにセットしたい ------- という感じです。
>>608 screen -X stuff hello
>>606 >>608 ` ` とか $( ) でコマンドの結果を利用できるけど、
プロンプトにちゃんと文字として入力させる方法は知りません。
コマンドの出力を利用するなら、
COMMAND_OUTPUT=`xxx` みたいに保存するとか、xclip を使うとか
誰かに、次はこのコマンド みたいに表示させるのが目的なら、
PS1="`xxx`\n" みたいにやって、プロンプトに表示しちゃうとか。
ちなみに、zsh なら `xxx` と入力した状態で TAB を押すと
`xxx` が hello みたいに xxx を実行した結果に書き変わる。
>>609 screen インストールしてみました。
確かにできました。
少し使いこなすの難しそうなので、いまいろいろ見てます。
>>610 コマンド一覧を表示し、そこから選んで、
それをその時々で好きに編集してから実行したかったんです。
結局は history の補完みたいになってしまうかもしれないけど、
少しイメージと違ったので、
自分でスクリプトでできないかと思っていたのですが、難しそうですね。
今日は名無しは「@そうだ選挙に行こう」だったのか。
>>610 >ちなみに、zsh なら `xxx` と入力した状態で TAB を押すと
>`xxx` が hello みたいに xxx を実行した結果に書き変わる。
すげ。さすがzsh
>>611 もう少し具体的に教えてもらえませんか?
こんなかんじですか?
$ command-menu
$ cd ls date cal #結果を編集して実行
---サンプル #!/bin/bash select var in \ 'cd' \ 'ls' \ 'date' \ 'cat' ; # 実際にはもっと長いコマンドたち do $var # ←ここ☆ break; done --- このサンプルだと、☆の部分で実行されてしまいますが、 そうではなく、その時々で好きに編集してから実行したい。 できればそれが history にも入るといい。 というわけです。
>>613 do
echo "$var";
echo "input argument <Ctrl+d>";
arg=`cat`;
echo "$var" "$arg"
"$var" "$arg"
break;
done
こんな感じにしてしまえばオプションとか入力できるようになる。
ただ、source hoge.sh みたいにしてこのスクリプトを呼び出さないと、
cd を選んでも 結果的には移動できてない ってことになるので、
alias で source hoge.sh を登録するとかしないとダメ。
> できればそれが history にも入るといい。
# bash の history のいじりかたはわかりません。
echo "$var" "$arg" >> ~/.command_history とかやって独自にログを残すとか。
>>613 select知りませんでした。
編集とヒストリ機能を付けました。
#!/bin/bash
set quit ls date cal
while true
do
select i in "$@" ; do
if [ "$i" = quit ]; then
quit=1
echo quit
break
fi
echo -n edit:
screen -X stuff "$i"
read cmd
if [ "$cmd" != "$i" ]; then
set $@ "$cmd"
$cmd
break
fi
$cmd
done
if [ -n "$quit" ]; then
break
fi
done
訂正 15行目 set $@ "$cmd" ↓ set "$@" "$cmd"
618 :
見習い@早くシェルマスタしたい :04/08/20 12:49
教えてくだしゃい シェルでsuを使用しユーザを変えてコマンド実行を行おうと考えているのですが su - root -c "ls -la" 0< passwd.txt とシェルを実行すると、リダイレクションの使い方が間違っているのか必ずパスワードを要求してきます。 出来れば自動的にコマンドを実行したいので、パスワードを返す方法を教えて頂けますか? ちなみに、Solaris9でシェルを実行しています。 シェルの凄い人教えて下さい。
>>618 まず君はシェルが何なのか解っていない
シェルとは何か
スクリプトとは何か
ボンさんにでも聞いてこい
>618 sudo ってないの哉?
>>620 、621
シェルの凄い方々回答有難うございました。
後はどちらが使いやすいか自分で試してみます
623 :
名無しさん@お腹いっぱい。 :04/08/23 14:32
すいません 質問です 算術演算子を変数に代入して演算したいのですができないのでしょうか? +、−、/、はできるのですが、¥*ができません。¥をつけるとできなくなってしまいます。 何かほかのやり方があるのでしょうか? 教えてください。 #!/bin/sh enzan="+" i=`expr 1 $enzan 1` echo " 1 $enzan 1 = $i" enzan1="\*" j=`expr 1 $enzan1 2` echo " 1 $enzan 2 = $j"
>623 eval alias bc
625 :
名無しさん@お腹いっぱい。 :04/08/23 15:30
>624 できました。 ありがとうございました
626 :
名無しさん@お腹いっぱい。 :04/08/23 22:01
psコマンドをwhileで廻して特定のプロセスが動いてるか確認したいんですが temporaryファイルを使用せずに、psコマンド自体がエラーになったら処理Aを、 プロセスが死んでたら処理Bを実行させるような条件式って出来るでしょうか? 分かる方いたらヒントお願いします
if hoge は コマンドの戻り値を受けてるんで その辺調べて何とやら
>>626 ps, pgrep と wc -l で似た様な事良くやるよ。
>>626 while ( ps ... || 処理A ) ;
do
STATUS=` ps ... ` ;
if [ $STATUSで判定 ] ; then
処理B
fi
STATUS=リセット
done
リセットは不要かな。
あと、処理A が実行された場合に、do 〜 done を実行して
while に戻っていいのか、終了するのかってのが必要かも。
> 特定のプロセスが動いてるか確認
killall -0 でも確認できるかも。
>>627 ,
>>628 自分なりに作ってみたんですが、psコマンドエラー時は何もしないとして
if [ `ps -ef;echo $?` != 0 && `ps -ef |grep hoge|grep -v grep |wc -l` = 0 ];then
プロセス停止時処理
fi
こんな感じかなと思ったんですが、結局&&の前と後ろでpsコマンド発行してるので
意味がないですよね・・・(涙)
も少し頑張ってみます。
psコマンドに-cオプション無いの?
>>632 今環境がないので分からないのですが、-cオプションってどういう機能ですか??
-c ``コマンド'' 桁の出力を、すべてのコマンドラインを表示するのではな く、実行形式名だけを表示するように変更します。 だからgrep -v grep要らなくなるかなと思って。スマソそれだけw
grep -v grep しなくて良いトリッキーな方法がこの板の過去スレにあった気がする。
ps -ef | grep '[h]oge'
(´-`).。oO(当り前のように使ってたからトリッキーだなんて微塵にも思って無かった…)
>>634 manで確認したんですがありませんでした<-cオプション
でもそれが使える環境でなら便利ですね。ありがとうございました
>>635 >>636 早速試してみます。
ところで今試してる条件式なんですが、psコマンドの発行を1度だけにして
実行できないものでしょうか?結局コマンドのエラー検知してもその後のps
コマンドでエラーが検知できないので。
自分で考えたロジックだとどうしても1回ファイルに出さないとダメな形になってしまうんです。
>>636 試してみた。出来た。でもなんでこれで出来るのかわからん。教えて。
>>639 PS="$(ps -ef)"
で変数に取っといておくってのはどお?
>>640 "[h]oge"という文字列は"[h]oge"という正規表現にマッチしないから。
>>642 あああああーーーーーー!!
そーゆーことか。
アリガトゴザイマス。
くだらないかもしれないですが質問です。 bash(RedhatLinux7.3)で文字列を数値型に変換したいのですが、うまいやり方はあるのでしょうか? '00001' => 1 '012' => 12 '2A' => エラー みたいな感じでできればOKです。 ・・・perlでいいじゃんってのは無しな方向でお願いします
何がくだらないってbashしかも特定のLinuxディストリ限定なとこだよね。 そんなの犬板でやれと。 まあbashどうこうは無視してこんな感じ? #!/bin/sh str=0011 if num=`expr "$str" + 0 2>/dev/null`; then echo OK: $num else echo NG. str is non-numeric. fi
>>646 ありがとうございます、感謝です。
bashやディストリは環境明示のために書いておいたものです。shのほうがよりgoodです。
心の広いUNIX板の方々に感謝しつつ、また仕事に戻ります。。。
dat 落ちで最後の方のレスを確認できないので質問します. 【貝】第1回シェル講座【殻】は,新スレを立てないで このスレを使うことに決まったのですか?
1000 まで逝かなかった希ガスる
>>646 ちょっときになったんだけど、コレ'0'とか'0000'とか渡すとNG扱いにならない?
まあ直すのも簡単だし仕様と言われればそれまでだけど。
あああ、確かに。あとstrに何も入ってない場合に0としてしまいますな。 条件追加してもいいけど、素直に:で正規表現マッチさせるべきだったか。
652 :
名無しさん@お腹いっぱい。 :04/09/02 00:25
はじめまして。 有識者の方、ご教示いただけないでしょうか? Solaris付属の in.ftpd では、オプションに -l -d を付けてやると、 セッション、コマンド等全てのログを syslog に送りますが (FTPのログを取る?inetdのログ?) 出力されているログの内容から 「どのユーザがいつログインしたか?」 「そのユーザがどのようなコマンドを使用したか?」 「そのユーザがいつログアウトしたか?」 の情報だけBシェルスクリプトで取れますか? 質問のしかたが悪かったらごめんなさい。 自分でも調べているのですがawkを使って 出力項目の何番目を抜き出す、までしか分からなくて。。 よろしくお願いいたします。
丸投げキター
手元にSolarisないからシラネ
変数に実行バイナリを放り込んで動かせないものでしょうか。 下のようなスクリプトを組んでみたんですが、if [ -x $hogehoge] までは期待した通りに 動くのですが、肝心の起動が出来ないようなので。 $hogehoge=/usr/local/delegate/bin/delegated case $ARGV in start) $hogehoge -P7810 -SERVER=pop3 ;; stop) $hogehoge -Fkill ;; esac
eval ? sh -c "" ?
>>655 >下のようなスクリプトを組んでみたんですが、if [ -x $hogehoge] までは期待した通りに
これはエラーになるはず。
>$hogehoge=/usr/local/delegate/bin/delegated
これもおかしい。
あ、hogehoge=/usr/loca/delegate/bin/delegated でした。
パラメータまで全部$hogehogeに突っ込んだらうまくいきました。 何でこうなるかはさっぱりですが。。。
>>655 hoge=ls
$hoge -l
普通にできるが。
イコールが悪さしてたみたいです。
tcshでcdの履歴を選択できるようにしたいと思っています。 今は、一覧表示と番号選択を別々にしています。 > cdl(一覧) 1 /usr 2 /home 3 /tmp > cds 2(選択) これをたとえば、、、 > cdl -> /usr /home /tmp みたいな感じで上下のカーソルキーで選び、移動したいと思っています。 このように上下のカーソルキーが押されたことを判定するような方法はあるんでしょうか? よろしければ教えてください。
>>662 シェルスクリプトじゃむずかしいから、rubyとかでcursesを使った
方がいいと思う。
>>663-665 レスthx
いろいろ眺めてますが入力の取り出し部分で
つまづいてます。
rubyの$stdin.getcとかしてみましたが
どうも改行しないとrubyに標準入力が渡らないようで...
もうちょっと調べてみます。
>>662 zsh なら, cd -[TAB] でだいたいできるけど.
sttyでいけることが分かりました。
rubyと格闘中ですが、なんとか動き出してます。情報どうもです。
>>667 zsh試してみましたが、cd -[TAB]だけ情報を見つけられませんでした。
ぐぐったら、cd ~-[TAB]だというのを見つけましたが、設定がかかれていないため試せず。。。
ワイルドカードと補完が強力なようですね。
ただ、うちの環境だとデフォルトでは色さえついてくれないので(ESCが表示されてしまう)
導入には道のりが遠そうです。。
669 :
名無しさん@お腹いっぱい。 :04/09/22 14:53:39
シェルスクリプトに関する質問。 1番目の引数、2番目の引数... は $1, $2, ... で参照できるやん。 例えば最初の3つの引数を標準出力に書き出すには echo $1 $2 $3 でええやん。そこでだ、”一番最後の引数”を取り出すにはどうすれば いいの? ”最後から2番目”の引数は? shで知りたいけどbashの場合でもいいから教えてちょ。
671 :
名無しさん@お腹いっぱい。 :04/09/22 15:57:03
指定した秒数の無音 WAV フォーマットのファイル (44100Hz 16Bit) をシェルスクリプトから作ることは可能でしょうか? C などの言語で書いたほうがいいでしょうか?
>>669 zsh なら
${*[$#]}
${*[$#-1]}
bash は知らない
s/$#/${#}/g
>>671 sox使って
< /dev/zero sox -t raw -r 44100 -w -s -c 2 - -t wav hoge.wav trim 0 10
とか.詳しくは
$ man sox
>>674 なるほど sox がありましたね。バイナリファイルをどうやって
作ろうかって悩んでました。ありがとう。
DATE=5 directory=`date --date '$DATE days ago' '+upload_%Y_%m%d'` mkdir $directory find upload -type f -daystart -mtime $DATE -exec mv {} $directory \; rmdir --ignore-fail-on-non-empty $directory こんな感じのスクリプトで定数を始めに変数にいれてから 使用したいのですがエラーになります date: invalid date `$DATE days ago' どのようにすればいいのでしょうか?
$DATEを括る '' を "" に、ってこと?
680 :
名無しさん@お腹いっぱい。 :04/09/23 05:27:17
$i と $j がファイル名だとする。この2つが「同一のもの」である時に 何か処理をしたいとする。次のように if [ $i = $j ] 文字列で比較すると、 i="file.dat" j="./file.dat" などの時に、同一のファイルであるにも関わらず失敗する。 なんかいい方法はないだろうか。ファイルのi-nodeをとりだせ ばいい?コマンド名教えてください。
681 :
名無しさん@お腹いっぱい。 :04/09/23 05:38:50
「同一のもの」を定義しないと意味無いよ
683 :
名無しさん@お腹いっぱい。 :04/09/23 07:42:15
>> 682 「同一のもの」= 同じi-nodeを持つファイル名 ?? なんか変な言い方だ。正確な用語は分からないが例をあげるので 類推してください。 ルートディレクトリに file.dat というファイルがあるとして, もしカレントディレクトリが/usr なら このfile.datを表現する 文字列 /file.dat ../file.dat /usr/../file.dat などは全部「同一のもの」。 $i と $j が「同一のもの」かチェックするのに if [ $(ls -i -d $i | awk '{print $1}' ) = \ $(ls -i -d $j | awk '{print $1}' ) ] ; then ... として自己解決しました。ls -i で i-node を見ることによって 同一かどうか判断している。おかしいところがあればご指摘お願い します。
いまだにシエルなんて使ってるの? いい加減にGUIビルダになさい
>>683 トイプログラムなのか、セキュリティが気になるプログラムなのかにもよるが、
後者なら
・ファイルシステムが違えば同じi-nodeのファイルが存在しうる
・i-nodeを使っていないファイルシステムをマウントした場合のls -iの挙動
・ハードリンクの扱い
なんかに注意
>>680-681 >>683 単純にファイル名(文字)で比較するなら、
basename と dirname でできると思う。
ディレクトリ名のチェックには
cd `dirname $i` とかやって、いったんそのディレクトリに移動して
pwd コマンドの出力とかを利用すれば比較できるはず。($PWD ってのがあるかも。)
cd するとかしないと、"." とか ".." が入ってるときに、
dirname の出力にもそのまま残ってしまう。
(戻る必要があるかわからないけど pushd , popd とかもある。)
>「同一のもの」= 同じi-nodeを持つファイル名 ??
シンボリックリンクだと、i-node は異なるはず。
中身の比較には diff とか md5sum とかもつかえる。
>>682 さん が指摘してるように定義をはっきりさせる必要がありそう。
>>683 if [ $i -ef $j ]
じゃだめ?
689 :
680 :04/09/23 14:16:27
>>685 >>686 自分用の半分使い捨てなシェルスクリプトです。なので自分の
使っている環境で考えれば i-node でみれば事は足りるのですが、
もっと汎用性のあるものを考えるならi-nodeでは不十分ですね。
>>686 にあるように $PWD から絶対パス名を取得してbasename,
dirnameでやる方が一番いいですね。簡単かつ確実。
>>687 ??
>>688 -ef 調べましたが分かりませんでした。これはなんですか?
こんなとこでreadlinkいわれても、俺にも??だ。
693 :
名無しさん@お腹いっぱい。 :04/09/23 19:35:22
済みません。教えてください。 rshで実行したコマンドの戻り値をcshで取りたいのですが、$statusだと rshの戻り値になってしまいリモートで実行したコマンドの戻り値になり ません(rsh自体は成功するのでコマンドがエラーでも結果が0で戻る)。 とりあえずググった結果、「sshを使え」と言う答えは見つけましたが、 rshでないといけない事情もあり・・・上手い手はないでしょうか?
rsh host 'false;echo $?' ってのはどうですか?
なるほど!試して見ます。 ありがとうございます!
>>694 うーん。駄目みたいです。「文法があいまいです」とか言われます。
(ちなみにSolaris8です)
rsh host 'false;echo $?'とか、rsh host 'false;echo $status'とか
rsh host 'false;exit $?'とか、rsh host 'false;exit $status'とか
'を`に変えてみたりしましたが・・・イマイチ。
今しようとしているのが、
1)AサーバからBサーバへrshでコマンド(シェル)実行
2)Bサーバの実行されたシェルからCサーバのシェルをrshで実行
3)Cサーバのコマンドの戻り値をAサーバへ返す
ということなんですが、BサーバとCサーバが同一サーバだったり
違ったりします(何で?とか言わないで下さい。前任者が作ったので)
なんかスタックみたいなモノに一時的に戻り値を入れて別のシェルから
取ったり出来ないでしょうか?出来なければかっこ悪いけどファイルを
作ってそれを読みに行くかぐらいしか・・・考え付かない。
Bシェルでファイル中の ' (アポストロフィ1つ) を ''(アポストロフィ2つ) に強制変換したいのですが、良い方法ありませんか? sed で変換しようとしたのですが、そうも正規表現の使い方が悪いせいか、手こずっています。 対象のファイルは、テキストファイルでアポストロフィの場所は、決まっていません。 アポストロフィ2つというのは、ダブルクォーテーションではなくて、ほんとに連続したアポストロフィのことです。
>>697 < hoge sed "s/'/''/g"
でだめですか?
Linux勉強中の者ですが、 sarのログ中に表示されている日付(m/d/y)を、表記順を変えて(Y/m/d)各行の先頭に挿入したいんです。 これを実現できるスクリプトなど教えて下さい。 元ログ--- Linux 2.4.18-14 (hogehoge.localhost) 09/23/04 00:00:00 %usr %nice %wio %idle 00:10:00 1 1 1 97 編集後のログ--- Linux 2.4.18-14 (hogehoge.localhost) 09/23/04 2004/09/23 00:00:00 %usr %nice %wio %idle 2004/09/23 00:10:00 1 1 1 97
#!/bin/sh read a echo $a set -- $a d=`date -d $4 +%Y/%m/%d` sed "/./s;^;$d ;" 要 GNU date。Linux なら入ってるだろ。 手元の環境には入ってないのでちゃんと動くかどうかは知らんが(w
>>698 教えていただいた方法で解決できました!
当初、sed 's/'/''/g' このような状態から思考錯誤していまして、
正規表現の問題かと思っていたのですが、
あっさり出来てしました。
レベルの低い質問で大変恐縮してます^^;
教授ありがとうございましたm(__)m
>>696 status=`rsh host 'false; echo $?'`
echo $status
とかではなくて?
「イマイチ」ってのが何がイマイチなのかイマイチわからん。
もっと具体的に、どうスクリプトを書いて、結果がどうなって、
実際にはどうなって欲しいのかを書いてくれ。
rsh でリモート側のシェルのステータスを取るには、
結果をファイルに落としておき
・1 行目には magic string(/number) を入れておいて
rsh がリモートを呼び出したことを保証
・2 行目にはシェルの exit status
・3 行目以降にはエラーの場合の、エラーの詳細
とかするけどね。
シェルのデバッガないの?
704 :
名無しさん@お腹いっぱい。 :04/09/25 02:39:23
英文の大文字を全部小文字にしたいんだけど、なるたけ標準的なコマンド できれいにやる方法ないかな。 cat eigo.txt | XXX でeigo.txtの中のアルファベット大文字が全部小文字に。俺はemacs で開いて編集してる。それでも数秒で終わるけどできればもっと簡単な 方法が知りたい。
トウpッペr
トォウェr
てー あー ーてー "「:うっぺr:」" "「:ろゑr:」"
>>704 man tr
cat eigo.txt | tr '[A-Z]' '[a-z]'
>>705-707 いくらなんでもそういう発想になるのは何故?
普通に書くより長いし w
元ネタがあるんですか?
710 :
名無しさん@お腹いっぱい。 :04/09/25 12:29:11
( sleep 10 ; cat /etc/passwd ) | ( cut -d : -f 1 ) ( sleep 10 ; cat /etc/passwd )& | ( cut -d : -f 1 ) ( sleep 10 ; cat /etc/passwd ) | ( cut -d : -f 1 ) & 上記の3つのスクリプトは、どれも2つのサブシェルが生成されますよね? でも2つ目がエラーになり3つ目が許される理由が解りません。 ただ単に文法的に許されないだけなのでしょうか?
711 :
名無しさん@お腹いっぱい。 :04/09/25 12:38:02
>>708 man tr
cat eigo.txt | tr A-Z a-z
tr での [] の使い方は性器表現のそれとは違う
>>710 & と | の組み合わせが構文的に許されていないからでしょう。
(( sleep 10 ; cat /etc/passwd )&) | ( cut -d : -f 1 )
ならおけ。
>>704 一つのコマンドでやるなら
$ dd if=giko.txt conv=lcase
住まん買った tr でやるのも一つのコマンドだ罠
715 :
名無しさん@お腹いっぱい。 :04/09/25 21:34:32
テキストファイルの途中に1行追加したくて 下のようなスクリプトを作ったんですが、 スペースが2つ以上続くと1つになってうまく動きません。 どうすれば良いのでしょうか? GREP_LINE="grep $2 $1 | sed -n -e '$ p'" mv $1 $1.bak while read LINE do echo $LINE >> $1 if [ "$GREP_LINE" = "$LINE" ] then echo $3 >> $1 fi done < $1.bak
>>715 > GREP_LINE="grep $2 $1 | sed -n -e '$ p'"
が謎だけど。
sed -e "/grep $2 $1 | sed -n -e '\$ p'/a\\
$3
" $1.bak >$1
あぼーん
変数にファイルサイズを得る方法 filesize=`ls -l $thefile | sed 's/^[-drwx]\{1,\}[[:blank:]]\{1,\}[[:digit:]]\{1,\}[[:blank:]]\{1,\}[[:graph:]]\{1,\}[[:blank:]]\{1,\}[[:graph:]]\{1,\}[[:blank:]]\{1,\}\([[:digit:]]\{1,\}\).*/\1/'` # awkとか言わないこと(ぉ
>>718 ls -s を加工したほうが楽じゃないか?
720 :
名無しさん@お腹いっぱい。 :04/09/26 00:27:29
拡張子を抽出するにはどうすればよろしいでしょうか? もし、拡張子がzipだったら・・・・ という処理がしたいです。
>>716 「テキストファイルの途中に1行追加したくて」という言葉を信じ
て、本当は単純に
sed "/$2/ a\\
$3" $1.bak > $1
ではないかと邪推したりしなかったり。どちらにしろ$2 とか $3
にメタキャラクタが入ってる場合を考慮するとメンドウだな〜
抽出 ext=$(expr "$f" : '.*\.\([^.]*\)$') .zipだったら〜 if expr "$f" : '.*\.zip$' >/dev/null; then echo ok fi
>>720 しかし、名前に頼らず file とか使った方が安全な気もするが。
case だろ?
>>38 エンタープライズなんていってる界隈のうにくすサーバーは、ジョブ制御なんてのをしなくちゃなんなくてね。1000行を超えてるしぇるすくりぷとなんてザラにあるのよ(w
727 :
おしえて :04/09/26 01:31:45
/etc/profile,~/bashrcでbashの組み込みコマンドのcdを無効にしても scriptコマンドを起動すると有効になります。 scriptコマンドを起動したまま、組み込みコマンドを有効にする方法ありますか。
>>726 ジョブ制御できるスクリプト言語なんて吐いて捨てるほどあるし、
そもそも昔の sh はジョブ制御できませんでしたが。
>>728 の/sbin には、static link された ruby が有るのだろう。
>>728 そのジョブ制御じゃないんだな。あれだ、メインフレームのジョブ制御の意味での制御なんだよ。
バッチ処理っていったらわかるかな?「JCLに相当するものをシェルで組め!」ってな要求がでてくるんだな。
お客さんの運用部門ってとこから。で、perlじゃダメ?って訊くと「ふざけるなぁ!」っておこらえるのさ。
ログの世代を次に送って、さっきまで使ってたファイルは圧縮して退避しとくなんてのを5つのシェルスクリプト
にばらして組めとかいわれるのよ。で、いわれたとおりにつくるような奴が開発担当すると1000行超えてるような
クラクラしちゃうシェルがぼこぼこできちゃうんだな(w
>>730 同じような境遇にいるけど、ログのローテはそれようのコマンド
探せばあるし、perlもなんとか説得してOKにしたよ。
UNIX のお仕事ってすごいですね.
>>730 > お客さんの運用部門ってとこから。で、perlじゃダメ?って訊くと「ふざけるなぁ!」っておこらえるのさ。
なぜおこらえるのか,もし良かったら教えていただけませんか?
シェルスクリプトを勉強するにあたって.
むしろログのローテと圧縮くらいでなんで1000行になるのか が分からん。その 1/100 から多くても 1/10 で組めるような 気がする。 まあ、元となる JCL が数1000行クラスなら、仕方ないかも しれんが。少なくともシェルスクリプトの方がJCLよりは 数倍短く書けるよな。
なんでperlでやりたいのかも分からん。
漏れのシェルスクリプト人生はSolarisの/usr/lib/newsyslogからはじまたよ・・・
OfficeのマクロもPerlで書くとか言い出しそう
シェルがぼこぼこできちゃうのは凄いな。
>>730 スケジューリング・キューイングされたジョブの実行や、
ユーザまたはプログラムからの即時のサブミット
ジョブの平行性管理
ジョブの監視や成功・失敗での子ジョブへの分岐
といった仕事がしたいんなら、日立のJP1とかその辺を使えばいいんじゃないかな。
上のような機能はshell自体には無いし、shellでそのマネゴトを
しようとしても多分無駄。
>>716 ,721
遅レスですみません。アドバイスありがとうございます。
echo使ってたからおかしかったんですね。
メタキャラクタは入らないのでなんとか出来そうです。
本当にありがとうございました!
>>739 うん、うん。そうだよねー。そうなんだよねー。
でも、どういうわけか、棒F社のSEさんたちは、いろんな管理ファイルを作っちゃって、
自社のミドルウェア機能をむりから使いまくってるから、「ログファイルの世代送りと圧縮退避」機能が
1000行越えのシェルスクリプト5つに化けてしまっているのね。
で、なぜだか客先のレビューも通過してて、稼動してからもう2年。
その間も、同じ経緯でぼこぼこ「バッチ」処理を増やしちゃってるから、目も当てらんない!
毎日のように障害発生!うんで、シェルスクリプト修正!緊急リリース!だって・・・
なにがなんだか・・・アタシは、なんで、こんなゴミの面倒を見る羽目になったのだろう?(泣)
743 :
名無しさん@お腹いっぱい。 :04/09/27 08:07:57
2行以上にまたがるかもしれない置換の仕方を教えてちょ。テキストファイルの 中の <title>foo</title> を <title>bar</title> に置換したいのだが <title> foo </title> とか <title> foo </title> とかにも適用できる方法を教えてちょ。なるたけ基本コマンド希望。
% gawk 'BEGIN{RS=ORS=SUBSEP}{gsub(/<title>[^<]*<\/title>/,"<title>bar</title>");print}'
745 :
名無しさん@お腹いっぱい。 :04/09/27 23:18:21
シェルスクリプトの質問とは少し違う気もするのですが、 find -name で[0-9]や*の正規表現は使えますが . は使えませんよね? UNIXのコマンドによって、正規表現が使えたりワイルドカードしか使えなかったり なにか基準のようなものはあるのでしょうか?
>で[0-9]や*の正規表現は使えますが . は使えませんよね? -name で指定するのは正規表現ではありません。 >なにか基準のようなものはあるのでしょうか? スクリプト言語以外で引数に正規表現を使えるコマンドなんて expr と grep 族とごく最近の find だけのような。ほかに何かあったっけ?
rshで・・・ psで・・・ findで・・・ のパターンが多すぎやしないか? この3つはunixの3悪コマンドなんじゃ?
うーん、奥が深い。
749 :
名無しさん@お腹いっぱい。 :04/09/28 23:39:37
スマソ file1.txt の n行目と file2.txt の n行目を 横にくっつけたいのですが・・ う〜ん つまり ::file1.txt ああ いい う〜ん ::file2.txt Oh Aha Un をくっつけて ああ Oh いい Aha う〜ん Un と出力したいのだがシェルスクリプトでどう書けばいいか おまいら 教えれ (Cで書けば10分以内に書けてしまうのだが この程度の処理をCで書くオレって変なんでしょうね)
FILE1=`cat file1.txt` FILE2=`cat file2.txt` i=0 while [ $i -lt 3 ] do echo ${FILE1[i]} ${FILE2[i]} i=$(( $i + 1 )) done
pasteなんてあったのか、、こりゃべんりだな
>>749 paste -d " " file1.txt file2.txt > output
でよくない?
タブで区切りたいのなら単純に
paste file1.txt file2.txt > output
シェルスクリプト初心者です。 他人のスクリプトを眺めてて不思議に感じました。 スクリプトはかなり省略してますが↓はどういう意味なんですか? (特に$が2つのあとに1が付いてるあたり) DropClient $$1 ~~~~~~~~~ ※DropClientとは自作関数のことです。
756 :
名無しさん@お腹いっぱい。 :04/09/29 22:08:35
>>755 普通は$$が自プロセスの番号におきかわるだけだと思うが
1くっつけて何が面白いのかはオレにはわからんな。
実は「他人のスクリプト」のファイル名がMakefileだったとか。
ども
>>755 です。
>>756 さん
$$の後に1を付けるのってヘンなことなんですか?
>>757 さん
*****.shってなってます。
実は*****.shの引数としてファイル名を一緒に受け取っていて、
そのファイルの中身を読み込み、値を各々の変数に入れてるという処理を前で行ってますが、
それと関係ありますか?
759 :
名無しさん@お腹いっぱい。 :04/09/30 17:01:11
IFS にタブだけを指定するにはどうすればいいのでしょうか? 本を読むと IFS=<tab> と書いてあるようなのですが、<tab> と書くのではないですよね? shll script を書くのに vi 上でこのようにしています。 IFS='' 上の空白は C-v C-i で作っています。 しかし、 IFS に何も指定しない時と、上のようにした時で動作が変わり ません。つまり、スペースもデリミタとして扱われてしまいます。
FS を使ってできました。
761 :
749 :04/09/30 21:02:26
>>750 知らなかった・・ _| ̄|○
以前、(一応肩書きは)システムエンジニアだったのに・・ _| ̄|○
10年前にはLinuxでhttpd動かしてたのに・・ _| ̄|○
BASICでプラグラム書いたのは四半世紀くらい前なのに・・_| ̄|○
Thanx
>>751 これは改造して便利に使いまわせそうだな
Thanx
762 :
名無しさん@お腹いっぱい。 :04/09/30 21:27:50
もっと汎用的な merge みたいなコマンドなかったけか?
awk
perl
grep
ed
Emacs
mule
769 :
名無しさん@お腹いっぱい。 :04/10/04 13:56:43
cc00・・・1 cc01・・・2 cc018・・・3 cc001・・・4 上記2〜4をgrepで出したいんですが 1だけは外したいんです。 どうすればいいですか?
% tail -3 filename | grep .
grep "cc0\(0.\|[^0]\+\)"
grep -v '1'
774 :
名無しさん@お腹いっぱい。 :04/10/05 19:51:03
grep -v '773'
#!/bin/sh exec > hoge.log echo hoge とすると echo の出力が標準出力ではなく hoge.log に入りますが、 #!/bin/sh exec | tee hoge.log echo hoge とすると hoge.log の中身はからっぽです。なんででしょう? hoge.log というファイル自体は作成されてるので tee は実行されてると思うのですが。
パイプはリダイレクションとは別扱いだからかな。 文法上の位置付けも違うし。 だから、単に exec を実行して、その結果を tee に渡しただけになる。 コマンドに渡したければ、OSによるが名前付きパイプをつかう。
うーむ、やっぱそうなんですか。 名前つきパイプだといろいろめんどくさいので、 #!/bin/sh ( いろいろ処理 ) | tee hoge.log としてスクリプト全体をサブシェルで実行するようにしちゃいました。
779 :
うさうさ :04/10/07 18:29:54
cp /local/lib/php.ini /local/lib/php.ini.ORG IFS= while read LINE; do if [ "$LINE" = ';mbstring.language = Japanese' ]; then echo 'mbstring.language = Japanese' >> /usr/local/lib/php.ini elif [ "$LINE" = ';mbstring.internal_encoding = EUC-JP' ]; then echo 'mbstring.internal_encoding = EUC-JP' >> /usr/local/lib/php .ini else echo "$LINE" >> /usr/local/lib/php.ini fi done < /usr/local/lib/php.ini.ORG php.ini の一部を変更したいのですが、 1098c1099 < ; crack.default_dictionary = "c:phplibcracklib_dict" --- > ; crack.default_dictionary = "c:\php\lib\cracklib_dict" こんなふうに \ がなくなってしまいます。。。 while で ファイルを読むのがいけないのかな・・・
シェルでやるのがいけない。
echo で行うのがだめみたいです・・・・ sed で行うしかないのか・・・
>>781 違う。read が '\' をエスケープ処理するからです。
だから
>>780 が「シェルでやるのがいけない」と言ってるんです。
「入力を変数に格納し、それを処理する」という
のをシェルだけでやるのは、read コマンドの仕様から無理なんです。
sed/awk/perl で頑張ってください。
でなければ、bash (とかの他のシェル)に逃げる。
while read -r LINE;
でうまくいくぞ。
この処理なら、sed でやるのが一番簡潔じゃない?
>>780 >>782 そうだったのか・・・
ありがとうございます。
bash つかってるんだけど、sh でも使えるよう sed でやることにします。
785 :
名無しさん@お腹いっぱい。 :04/10/08 14:42:14
下のように"/"文字の置き換えをしたいのですが、どうすればいいのですか? "/TOOLS/WORK" ↓ "__TOOLS__WORK"
>>785 tr で -s を使う。
sed で y を使う、sとg を使う。
ほかにもやりかたはいっぱいあると思う。
787 :
名無しさん@お腹いっぱい。 :04/10/08 16:07:34
下のスクリプトでやってみたのですが、失敗。 "/"の記述がダメなようです。 どう書けばいいのですか? #!/bin/ksh var=/\TOOL/\WORK echo ${var}|sed 's///__/g'
>>787 スラッシュとバックスラッシュが逆なんすけど。
echo ${var} してみそ。
それだけじゃなかったわ。 上のvar= で\使っててるなら、下でもいると思うけど...。
790 :
名無しさん@お腹いっぱい。 :04/10/08 16:32:51
>>788 さん ありがとうございました
うまくいきました。
#!/bin/ksh
var=/\TOOL/\WORK
echo ${var}|sed 's/\//__/g'
sedの区切り文字は/じゃなくて何でもいいのよ。s%/%_%gとか。
あるディレクトリの中のディレクトリが3分程経ったら消去するスクリプトを作りたいのですが・・・ cronで1分毎に起動して・・・ 後、わからん・・・
sleep 180;rmdir hoge/hoge
?
リモートシェルを起動するときID/パスワードを入力引数として渡したいんですが、 シェルでどう書いたらいいんですか?
完全にFAQなので、ちょっとはぐぐれ。expect。 しかし ssh-agent を使った認証を禿しく勧める。
797 :
名無しさん@お腹いっぱい。 :04/10/08 22:57:43
>>779 sed なら
cp /usr/local/lib/php.ini /usr/local/lib/php.ini.ORG
sed 's/^;mbstring\.\(language = Japanese\|internal_encoding = EUC-JP\)$/mbstring.\1/' /usr/local/lib/php.ini.ORG > /usr/local/lib/php.ini
かな。もしかしたら GNU 拡張な BRE 使ってるかも〜
>>797 ちょっとググっただけじゃ分からなかったんだけれども,
その動作が POSIX かどうかって,どうやって調べるんですか?
最近気になるのは head の -c オプション.
802 :
名無しさん@お腹いっぱい。 :04/10/09 14:17:12
初めてのシェルスクリプトです。 先生方、採点お願いします。 /* 引数1(Directory)内の圧縮ファイルを全て解凍する */ #!/bin/bash if [ ! -d $1 ] then echo "$1 is not directory" echo "Usage: `basename $0` directory" exit 1 fi for list in `ls $1` do [ ! -f $list ] && exit 1 case $list in *.zip ) unzip $list ;; *.lzh ) lha e $list ;; * ) : ;; esac done
採点もなにも、自分で実行してないと思われるので0点。 まず引数を与えて実行してみよう。 デバッグには -x オプションが役に立つ。
804 :
名無しさん@お腹いっぱい。 :04/10/09 16:17:14
当然実行しましたよ。目的は果たせています。 コピペなのでタイプミスなんかも無いはずなんですが.... 突っ込みどころ満載なんじゃないかな。 とアドバイスを求めた次第です。
あ、コメントの /* */ は後から書きました。当然bashで無いのは自覚しています。
採点って何だ? 自分がやりたいことが実現できてればそれでいいんじゃないか?
仕様を満たしていないので0点。 > 引数1(Directory)内の圧縮ファイルを*全て*解凍する
そもそもなんでそんな仕様なんだ?
エラーメッセージはstderrに出す。-20点
#!/bin/bashだから-20点
>>807 とあわせて-40点
zipの中のファイル名が重なっていると勝手に上書き、若しくは確認を求めて終了しない。 -20点
目的は果たせてるそうだから、100点でいいじゃない。
>>792 です
あるディレクトリの中のディレクトリが3分程経ったら消去するスクリプトを作りたいのですが・・・
cronで1分毎に起動して・・・
正確には、
/buff/index.html
/buff/hoge1/hogeA.hoge
/buff/hoge2/hogeB.hoge
/buff/hoge3/hogeC.hoge
・
・
・
のhoge*のディレクトリが作成されてから3分以上経ったら中にあるファイル丸ごと消去する。
/buff/index.は消さない。
これをcronで1分毎に起動して古くなったディレクトリとその中身を消去する。
ディレクトリのタイムスタンプを見る必要があるのでしょうね。
また、>793のままだとディレクトリの中に何かあればエラーになると思いますが・・・
勉強中
>>809 #! /bin/sh と書いてありながら bash 独自のを使うよりいいんじゃないかな?
え,そんなことしたら -inf ですかそうですか.
>>813 > #! /bin/sh と書いてありながら bash 独自のを使うよりいいんじゃないかな?
#!/bin/bash なんてないんですけど。
引数1(Directory)内にディレクトリがあったら終了してしまう。-20点
>>804 動くはず無いもの、君嘘ついてるでしょ。宿題は自分でやりなさい。
818 :
名無しさん@お腹いっぱい。 :04/10/09 18:27:40
先生方、暖かいアドバイスをありがとうございます。
>>817 動いているのですが...
ダウンロードしたエロ動画を一括解凍するスクリプト...
宿題のわけがありません。
/bin/bash は FreeBSD とかにはないから、それでうごかないと言われているんでそ。
引数なしで起動すると動かない。
>>804 803だが……。実行してないってのはちゃんと仕様を満たすか
テストしてないってことだ。$1='.'の場合以外にまともに動作するとは思えんし
>>816 のバグもある。
なんでそんなに堂々としているかの方が不思議だ。
>>821 どうせ自分専用の使い捨てスクリプトなんだから
>>802 が満足してるならそれでいいじゃん。
エロ用スクリプトなんだろ? オナニーできればそれでいいじゃん.
実は俺達は羞恥プレイにつき合わされてたんだよー
ディレクトリツリー内の各ディレクトリに対して そこをカレントディレクトリにしてコマンドを実行するにはどうすればいい? find -type d -exec ... じゃ無理っぽい.
find .. -type d -exec sh -c 'cd {}; コマンド' ';'
可憐とディレクトリにする理由が知りたいな.
831 :
名無しさん@お腹いっぱい :04/10/10 08:39:05
シェルスクリプトの実行って早いんですか?
漏れがコマンドを実行するより速いな。
実行が速いかは分からないが, シェルスクリプトにすると作業が早く終わる.
>>821 なるほど。たしかに$1='.'以外では動きませんね。
for file in $1/*
do
case "$file" in
*.zip ) unzip "$file" ;;
*.lzh ) lha e "$file" ;;
* ) : ;;
esac
done
>>829 thx. -exec sh とは気付かなかった
>>830 ソースツリー内でctags -Rを乱発したかった
/home/hogeの中にある不特定多数のディレクトリ(中にファイル有り)を、 その不特定多数のディレクトリが更新(作成)後、約5分経ったら中身ごと削除する・・・ find /home/hoge -type d -mmin +5 | xargs rm -drf {} これを cron で1分毎に起動する。 (1分毎に起動されるので、実際には5〜6分は生きていることになります) rm を使うのでちょっと怖いのですが、どうでしょうか? 初心者です。よろしくです。m(__)m
何がしたいんだか。
ここにランダムな名前でディレクトリを作り、その中のファイルへリダイレクトさせようと・・・ で、一定時間が経ったらディレクトリごと消去することで、直接リンクを防止できないか?と。
すいません。誤記修正します。 × /home/hogeの中にある不特定多数のディレクトリ(中にファイル有り)を、 ○ /home/hogeの階層下にある不特定多数のディレクトリ(中にファイル有り)を、
5分ごとに全消しすればいいじゃない。 どうせ10分生きてたってたいした影響ないんだろ?
842 :
名無しさん@お腹いっぱい@837 :04/10/14 05:12:00
@837です。
要は、5分ほどの間、ディレクトリ(及び、その中のファイル)の生存を保証したい。
>>841 の方法だと、cron が回ってくる直前に更新(作成)されたディレクトリ(及び、その中のファイル)は極端に寿命が短くなる。
cron で1分毎に起動され、その際に既に5分以上経過しているディレクトリは消去するようにすれば、最短で5分、最長でも6分弱の間は生存できることになる。
cron 起動間隔分の誤差は生じるが、これで十分。
仮に cron が1秒毎に起動できるならば、最短で5分、最長で5分1秒弱になるが、システム負荷が大きくなるだけなので、そこまでやる気は無い・・・
どこをどうしたらそんな奇妙奇天烈な要求が出るのかというのが知りたいところでは。
844 :
名無しさん@お腹いっぱい。 :04/10/14 05:53:59
>>837 それはダメだね。{}というディレクトリがどうなるかよ〜く考えてみよう。
xargs の弊害だね、どこから -exec を使わないでxargsをもてはやす風潮が
生まれてきたんだか。
>>844 >>837 のは単にモノを理解してないだけじゃん。
xargsの方がプロセス少なくて済むから-execよりxargs使った方がいい場面は多
いと思うが。何偉そうに言ってんだ?
なんで? xargs の方が トータルで 1 個多いと思うが。 rm はどちらも同じ回数起動されるよ。
>{}というディレクトリがどうなるかよ〜く考えてみよう。 え?コレぢゃダメですか・・・ find /home/hoge -type d -mmin +5 -exec rm -drf {} だと、100個以上ではエラーになると聞いたので・・・
>>847 rm a
rm b
rm c
と
rm a b c
どっちが多いかわかる?
5分毎にディレクトリ名を変えるのじゃだめなの? 直接リンクを防止という要求は満たすような気がするのだが。
お騒がせしております。m(__)m 結局、次の通りと思うのですがいかがでしょうか? -exec と xargs がゴッチャになってまして、\;が抜けていました。 @ find /home/hoge -type d -mmin +5 -exec rm -drf {} \; A find /home/hoge -type d -mmin +5 | xargs rm -drf {} 速度 バッファ消費 その他 @ 遅い 少ない 遅いが確実に作動する A 早い 多い 大量の引数を持たせない限り早い いかがでしょうか?
(日)(月)
>>850 UPLOADERに使った際に、1つのダウンロード毎に全くランダムな名前をMySQLの
ユニークキー機能で確認しながら作り出し、その名前のディレクトリを作るつもりです。
(半角大文字小文字の英数字で30文字ほど)
そのディレクトリの中にデータを入れておき、リダイレクトさせる・・・
で、5分ほどでディレクトリごと消します。
てなワケで、ダウンロードのurlの搾取は事実上不可能にしようと・・・
HDDの負荷は大きいですけどね。
もしかしてユニークキーだけのためにMySQL使うの? 牛刀だなあ……。
>>854 いくらなんでも、そんな・・・
もたいない。
>>851 xargs もまちがってるじゃん。
一回自爆してから勉強しなおしたほうがいいと思う。
857 :
名無しさん@お腹いっぱい@837 :04/10/14 20:54:14
>>856 find /home/hoge -type d -mmin +5 | xargs -O rm -drf {}
?
ちゃんと読まずに書くけど find /home/hoge -type d -mmin +5 -print | xargs rm -drf でいいんぢゃないの
なんで xargs に {} なんて引数入れるんだよ。
857で指摘してあるだろ
find /home/hoge -type d -mmin +5 | xargs -O rm -drf
最近、ルータの調子が悪いので、鯖から、外部へつながらなくなったら 鯖をシャットダウンをしたいんですが、 なにかいい方法はないもんでしょうか。 pingうって、帰ってこなければ、シャットダウンとかおもうんですが、 pingが帰ってこないのをどう処理すればいいのかさっぱりなんですが。
man ping
865 :
名無しさん@お腹いっぱい。 :04/10/16 00:36:01
質問なので age ます。 #!/bin/sh OPT= if [ $# -eq 0 ] ; then echo no_arg fi while getopts as OPT do case $OPT in a) echo aaa ;; s) echo sss ;; \?) echo NG 1>&2 ; exit 1;; esac done exit 0 引数なしのとき、-x のような指定外のオプションを弾くときは こんな感じでいいと思うのですが、 たとえば引数に a が与えられたときのエラー処理は どうするのがスマートなんでしょうか
echo $?
>>866 done
+ if [ $? -ne 0 ]; then
+ echo ng; exit 1;
+ fi
+
exit 0
こういう使い方をしてみたのですが、ダメですね。
-a でも a でも $? は 0 になってしまうようです
それとも、意図と違いますか?
>863 pingを一発うって、grepって、100%ロスだったら処理すればいいだけでは・・・
>865 getoptじゃだめなの?
getopt って getopts より高機能なの?
>>863 if ping どっか;then
生きてるしょり
else
死んでる処理
fi
こんなかんじの結構よく書く
874 :
名無しさん@お腹いっぱい。 :04/10/22 11:24:17
質問です UNIXのシェルでは while中の入力はできないのでしょうか? ファイルから一行ずつ読み込んでいくwhile文中 YES/NO判定をしようとしたら、 文字入力のループ内を入力を受け付けないまま無限ループしてしまったので・・・ 携帯からなのでソースを乗せれないためわかりにくいと思いますが、解決法をご存じの方お願いします
わかりづらくてすいません。もう少し詳しく説明します while [ read -r a.data ]do というa.txtというファイル内のデータについて処理するループで、特定のデータが出てきたら if yesno; then という風に関数を呼び出すようにしています。yesno関数内では、文字の判定を行なうループを作り、 「YNを入力してください〉」というメッセージを出力させ readで入力された文字を変数に格納しています。 そしてYなら1を Nなら0をreturnしています。それ以外なら「Y/N以外は入力できません。」のメッセージの後再入力させるようにしています メイン処理に戻ったら、Yなら終了、Nなら継続というようにしているのですが、 Y/N判定ループに飛んだ後、 「YNを入力してください〉」 「Y/N以外は入力できません。」 が永遠に繰り返され 入力することができません この状態を解決する方法を探しているのですが、この説明でわかりますでしょうか? よろしくお願いします
>>876 まず、"read -r" って sh じゃなくて bash じゃないのか?
# bash を #!/bin/sh で呼び出したら動くとかいう寝言は却下ねw
> while [ read -r a.data ]do
・while コマンドの書式を理解している?
・[ が何かを理解している?
>>876 まず [ ]をとっぱらえ
話はそれからだ。
[ ]を作ったやつはバカだ。知らない人が見たら while (condition) と while [condition]は同じ意味だと誤解する。
何をどう工夫して作ったって、「知らない人が見たら」同じことだろ。
「[ ]」よりむしろ「.」コマンドの方が驚きだ。 man . するとmanがディレクトリのハードリンクの「..」と混同して警告吐く
どこのmanだそりゃ。
>>881 `.' というコマンドを持っていないのですが,それは何ですか?
>>879 bash は好きですがどうしても `test' と書いてしまいます.
だって `[' `]' はワイルドカードに使われるし,`-gt' が英単語なんだし.
ところで
test "x$var" == "x"
と書くのは何故ですか? やはり `-n' や `-z' は分かりづらい?
`.'はシェルの組込みコマンドだ。 man sh 嫁。
>>883 ありがとーございます。
Solaris 9 で man sh で確認したんですが…
man -s 1 read では書いてありましたです。
>>882 Solaris9 で man . すると死ねますが。
truss してみたところ、なぜか
/usr/share/man/sman1/.
に hit するみたいですw
とりあえずシェル書くやつはリターンコードが何かを理解したほうがよさげだな。 わかってないやつが書くコードは冗長すぎてみてらんない。
889 :
名無しさん@お腹いっぱい。 :04/10/23 10:25:06
シェル書く奴って。
>>874 if yesno < /dev/tty; then blah; fi
>>888 たしかにろくな文章にヒットしてないな・・・
いやさ、
>>874 だってさwhileのループ条件がwhileの次のコマンドのリターンコードだって理解していないみたいだしさ。
>>871 のリンク先だっていちいち$?をifとtestで判別してるし。
コマンドそのものをifの引数にとればいいんだよ。
あと||とか&&とかもけっこうつかえるしね。
・・・シェル読みなれてないやつにはわかりにくくなるかもしれんが。
>>892 > ・・・シェル読みなれてないやつにはわかりにくくなるかもしれんが。
結局ここに行き着くんだよな。
俺は正しい処理してるなら好きに書けと言うスタンスだ。
多少効率落ちても読みやすい方を取る。
詳しくないんで教えて欲しいんだが、
>>889 の答えってどういう意味?
というか、そもそも test "x$var" == "x" なんて書き方する?
"$var" == "" ならよく見るが・・・・
>>894 [ "$var" == "" ]
って書くやつは、$var に "-h" や "" が入ってきたらって
考えないのかねぇ、ってことだ。とりあえずコード書いて試せ、
話はそれからだ。
試しても気付かないと思われ。
色々調べた結果です。 ひょっとして、こういうことが言いたいのかな? [ $var == "" ] ←$varをダブルクォーテーションで囲まない だと、varの値がnullの場合に「$var」の部分が消えてしまって [ == "" ] となり、エラーになる。 また、varの値が「-h」等、testのオプションにあるものだと、 [ -h == "" ] となって、「-h」がtestのオプションとして解釈されてしまう。 で、それらを避けるために「x」をつけておく、と。 でも、もしそういうことなら、今回の場合は$varが "" で囲って あるから問題ないんじゃないの? 万一付け忘れた時のために、「x」を付ける習慣をつけておく、ってことかな?
途中まではいいのに、なんで最後の三行がそうなるかな。
>>897 おまいの環境のechoに`-n'オプションがあるなら
$ echo "-n" "abc"
試してみろ。
>>898 > 途中まではいいのに、なんで最後の三行がそうなるかな。
最近のシステム(少なくともPOSIX準拠のシステム)であれば
> でも、もしそういうことなら、今回の場合は$varが "" で囲って
> あるから問題ないんじゃないの?
ってのは正しい。
>
>>900 echo(1)の場合とtest(1)の場合は区別して考えましょう。
救いようがないな。
903 :
从*・ 。.・从 ◆SayuminPM. :04/10/24 13:14:35
ありえれいな
「詰めが甘い」とか言っている香具師は $varが""や"-h"のときに if [ "$var" = "" ]; then ... fi って書き方が実際に問題となるシステムを挙げてくれないか?
var="!"
うわー今まで "x$var" == にしていなかったよ. configure スクリプトがやってるから, なんとなくやっておいた方がいいのかな.
>>46 そんなメリットがあったのかー!
気がつかなかったぜ
#!/bin/sh
var=""
if [ "$var" == "" ]
then
echo "-n" "true"
else
echo "-n" "false"
fi
<実行結果>
hoge$ sample.sh
truehoge$
<実行結果> var="-h"の場合
hoge$ sample.sh
falsehoge$
GNU bash, version 2.05b.0
この結果を見ると、
>>901 氏
>>904 氏が正しいようですが・・・・
bashで試されてもなあ。
ちゃんとした/bin/shのあるOSで
>>905 をよろしく。
>>901 ""で囲ってあれば問題にならないのは$varがnullのときだけで。
$var=-hの場合、ビルトインコマンドであっても""の有無はコマンドには知らされないから
testはオプションと解釈する。
#!/bin/sh var="" if [ "$var" = "" ]; then echo 'あいえれいな' else echo 'ハァ━━━━━━ ;´Д` ━━━━━━ン!!!!' fi SunOS edu 5.8 Generic_108528-19 sun4u sparc SUNW,Ultra-Enterprise $var="!" ./hoge.sh: test: 引数が足りません。 IRIX64 ed1 6.5 10120104 IP27 $var="!" ./hoge.sh[3]: test: 引数がありません ハァ━━━━━━ ;´Д` ━━━━━━ン!!!! var="-h" var="" は問題いようだ
>>910 いやそれが、阿呆な使い方を許容するためにCFGを超えて面倒なことをしてるんですよ。
*BSDだとtest.cの中のisoperand()。
それでも
>>905 のケースには対応できてないが。
Linuxでもtest(1)は対応できない。
>>909 持ってない・・・・
が、一応やってみた。
結果は「false」。
if [ =="" ]; then ... でやると「true」になるので真偽が逆転したわけか。なるほど。
>>910 var="-h"
if [ "$var" /bin/sh ]; then ... は確かに「true」になった。(/bin/shはbashへのシンボリックリンク)
[ "$var" == ""]でvar="-h"の時は、結局、[ -h =="" ]と同じになって、
「==""」の部分がファイル名として解釈され、
そんなファイルは存在しないので「false」になったわけですか。納得。
あと、var=""のときも確かにエラーにならなかった。
[ =="" ]で「true」と判定されました。両辺ともnullだから、というわけか。
うーん、勉強になるなぁ
914 :
名無しさん@お腹いっぱい。 :04/10/24 15:46:38
( ゚д゚)ポカーン
>>913 == じゃなくて =
それから、引数の間にはスペースを入れろ
>>915 ご指摘ありがとうございます。
スペースの件は知っていたのですが見落としました。気をつけます。
== はあまり気にせず発端の
>>884 に合わせてたんですが、
reference等を見るとすべて = となっているのでこちらが
正式なのですよね。== が許されるのはまた「bashだから」
とかなのかな。
以後、= で統一します。
全部 /bin/zsh で書くヲレは勝組
シェルスクリプト書くやつは負け組
>>916 ≫ == はあまり気にせず発端の
>>884 に合わせてたんですが、
ものすごい勢いの勝ち組だ…
ftpサーバにログインしてそこに aaa というディレクトリがなければ
それをつくるというようなスクリプトを作りたいのですが、
ディレクトリの有無を調べるにはどうしたらよいでしょうか。
curl --list-only
ftp:...... でリストをつくるまではいったのですが
>>920 ftp の標準入力に実行したいコマンドをつっこんで、
ftpdのレスポンスをリダイレクトして、ファイルに落とす。
そこで、sedなんかでリターンコードを見て成功したかどうかチェック
>>920 とりあえずftp鯖とお話したいならexpectではなかろうか。
シェルには荷が重い希ガス。
つーか autoexpect で 糸冬 了 ズザザ━━━━⊂(゚Д゚⊂⌒`つ≡≡≡━━━━!!
すまん・・・ いきなりだがシェルの実行方法を教えてくれないか? 例えば csh ファイル名 とかでそのファイルに書かれたシェルスクリプトを実行できるのだが、 ファイル名だけをコマンドラインから打って実行する方法が あるらしいのだが、デキナイ・・ファイル名の事をそんなコマンドはネーヨ!! とか言われて勘違いされるのだが・・・ 何か設定しなければならないことあるのか? ヒントだけでもいいからオクレ
・・・実行権つけれ
カレントディレクトりにパスが通ってないんじゃないか。 パスと押すのはオススメしないので、 ./hoge とでもしろ。
alias ほげ 'csh ほげ'
============================ #!/usr/bin/sh echo test ============================ ファイルの中身が↑だと「見つかりません」とかでて ファイルの中身を↓のようにすると、上手くいきます。 #!/usr/bin/shが悪さをしているのだと思うのですが コマンドwhich sh で表示させたところ /usr/bin/shだと言ってます、パスあってるよなー。 crontabでcshスクリプトを定期的に実行したいので ============================= echo test ============================= AIX5.1です。
/usr/bin/shだと言ってます、パスあってるよなー。 ls で確認くらいしてから書き込めヴぉけ。 ふつう sh は /bin/sh だけど。
#!がshなのに中身はcshスクリプトなの?
エスパーが必要とされている。
とりあえず、ためしに作っただけです。 echoならcshでも動きますよね。 それと行頭のパスはあってます。 ちなみに/bin/shにしても結果はかわりませんでした。
/usr/bin/sh が存在する OS は少なくないぞ。 それはそれとして、Windows のエディタでスクリプトを書いて ftp で転送するとそういうことが起きることがある。
エスパーキター!!
>>933 それです、今それをやってます!!
解決しました。 933ありがとう・・。 しかしwindowsマシンで 作れないとすると・・どうすりゃいいんだ? viエディタなんて使いたくない!!
binary モーどで送ればいいじゃないの。a
というかだ。 924は勉強しろ。 いろいろと
ところでちょっと聞きたいんだけど、自分はスクリプト書くときに変数は囲め るときはなるべく "" で囲むようにしてるんだけど変ですかね…。
ls -al | などでパイプを通ってきた文字列に"abcd"という文字列がふくまれているかどうか テストしたいのですがどうしたらいいでしょうか? あるいはパイプを通ってきた文字列をなにか変数に格納する方法などありましたら おしえてください。
ls -al|grep abcd
>>940 いいことだと思う。
囲んでないと、
スペースを含んでたりしたときにおかしな動作になることがある。
対処方はいろいろあるんだろうけど。
>>943 レスありがとうございます
ls -al | grep abc | test --(なんとか)&& echo succeed
みたいなことをやりたいのですが、このテストの部分でなにかいい方法がない
でしょうか
ls -al | grep abc > testfile ; test -s <testfile && echo exist
とファイルに落とすとうまくいくのですが、直接受け渡しはできないでしょうか。
if ls -al|grep abc >/dev/null 2>/dev/null ; then echo succeed fi
>>945 それから、testは標準入力は読まないと思うから、
test -s testfile && echo exist
だから`つかえって var=`ls -al` でコマンドの出力を変数に代入できる。
>>946 ,947,948
ありがとうございます。おかげさまでスクリプトがだいぶんすっきりと
まとまっていきそうです。
ところで
if ls -al|grep abc >/dev/null 2>/dev/null ; then
echo succeed
fi
これでうまくゆくのですが、どうしてうまくゆくのかわかりません。
どこでtestしているのですか?
>/dev/null 2>/dev/null と続けて/dev/nullに上書きしているようにおもえるのですが。
if は次に記述されるコマンド(正確にはパイプライン・・コマンドをパイプで連結したもの) のリターンコードを見てる。 testは引数の結果でリターンコード変えてるんだよ。
>>950 なんどもありがとうございます。
|grep > /dev/null
のところでなにか/dev/nullに送られたかどうかをtestしているという理解でいいでしょうか?
二つ目の
2>/dev/null
は必要なものでしょうか。
>>951 chmod 000 /dev/null とかやって見れば?
>>951 >のところでなにか/dev/nullに送られたかどうかをtestしているという理解でいいでしょうか?
だめです。
grepは文字列が見つかれば0を返し、そうでなければ1を返します。
返事が返ってきた 返事が返ってきた ↓ ↓ 鸚鵡返しに質問 ちょっと調べてみる(考えてる) ↓ ↓ ありがとう ありがとう
>>953 >/dev/null 2>/dev/null を消したスクリプトで試してみて
意味が納得できました。
ほんとにありがとうございました。
コマンドラインからgrepやってみて echo $? とやりゃ分かる