シェルスクリプト総合 その5
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
2006/01/21(土) 09:00:29スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。
□お約束
・特記なき場合はbourne shがデフォルトです。
bash/csh/tcsh/zsh/ksh/ashなどに依存する場合は明示しましょう。
Linuxユーザは/bin/shの正体がbashなので特に注意。
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
manや参考リンクを見ましょう。
aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
0750名無しさん@お腹いっぱい。
2006/03/17(金) 00:33:46manも--helpオプションも間違ってて、
ソース読まざるをえないことが数度あった。
bashとかのでかいmanはよみにくいな。
0751名無しさん@お腹いっぱい。
2006/03/17(金) 00:37:040752名無しさん@お腹いっぱい。
2006/03/17(金) 00:43:180753名無しさん@お腹いっぱい。
2006/03/17(金) 00:52:25ああいうのなら info の方がいい。
0754名無しさん@お腹いっぱい。
2006/03/17(金) 01:18:200755名無しさん@お腹いっぱい。
2006/03/17(金) 01:20:07Solarisのmanは、docs.sun.comと同じソースで、
かなり前からSGMLドキュメントがオリジナルになっている。
アンサーブックの時代にそうなった。
/usr/man/sman*
0756名無しさん@お腹いっぱい。
2006/03/17(金) 06:56:130757名無しさん@お腹いっぱい。
2006/03/17(金) 07:16:05for i in *; do mv "$i" "`echo "$i" | tr a-z A-Z`"; done
0758名無しさん@お腹いっぱい。
2006/03/17(金) 07:18:360759名無しさん@お腹いっぱい。
2006/03/17(金) 07:24:110760名無しさん@お腹いっぱい。
2006/03/17(金) 07:32:58なんで突然UNIXを打たなきゃなんなかったのか気になる
0761名無しさん@お腹いっぱい。
2006/03/17(金) 08:19:02Solarisのインストール時に、最小インストールを選択すると manは入らないよ。
サーバー専用機などで Xが不要の場合、
End Userインストールより下には最小インストールしか選択肢がなく、
それを選んで manなしになっているマシンは多い。
0762名無しさん@お腹いっぱい。
2006/03/17(金) 08:20:400763名無しさん@お腹いっぱい。
2006/03/17(金) 08:53:220764名無しさん@お腹いっぱい。
2006/03/17(金) 09:08:36しかも、manは実行ファイルでもあるまいし、サーバー専用機の場合、
サーバー機にloginしてmanを読むこと自体無駄。
あ、だからdocs.sun.comなのか。
0765名無しさん@お腹いっぱい。
2006/03/17(金) 10:41:41NFSでman積めば?
0766名無しさん@お腹いっぱい。
2006/03/17(金) 11:05:400767名無しさん@お腹いっぱい。
2006/03/17(金) 11:09:48情報を後出しされてもなぁ
じゃmanサーバ立てて都度読みに行けば?
0768名無しさん@お腹いっぱい。
2006/03/17(金) 11:22:58けち臭いこというなw
0769名無しさん@お腹いっぱい。
2006/03/17(金) 11:45:580770名無しさん@お腹いっぱい。
2006/03/17(金) 11:55:43find / -type f -atime +365 -exec rm -f {} \;
でも実行しとけ
0771名無しさん@お腹いっぱい。
2006/03/17(金) 12:07:54多数のマシンに pkgadd して回るなんて面倒なことはできない。
デフォで入らなかったというのはそれはそれで意味があるのだろうし、
あえてデフォの状態をいじりたくないというのもある。
0772名無しさん@お腹いっぱい。
2006/03/17(金) 12:10:40それをシェルスレで主張する意味がわからん。
0773名無しさん@お腹いっぱい。
2006/03/17(金) 12:10:480774名無しさん@お腹いっぱい。
2006/03/17(金) 12:13:170775名無しさん@お腹いっぱい。
2006/03/17(金) 12:30:59そうだよ、入れなきゃいいんだよ。
オレは入れるなとは主張していない。
「manくらい入れろ」と言ってる >>762 とかに
反論してるだけ。
0776名無しさん@お腹いっぱい。
2006/03/17(金) 12:45:430777名無しさん@お腹いっぱい。
2006/03/17(金) 13:01:09このスレで質問したことは一度もない。
回答は多数。
初心者の質問に、誰かが man嫁と回答してるのを見て、
その直後にもっとずばりの回答をしてるのがオレ。
manなんかで回答するんじゃないぞ。
0778名無しさん@お腹いっぱい。
2006/03/17(金) 13:29:250779名無しさん@お腹いっぱい。
2006/03/17(金) 13:30:420780名無しさん@お腹いっぱい。
2006/03/17(金) 13:31:280781名無しさん@お腹いっぱい。
2006/03/17(金) 13:51:050782名無しさん@お腹いっぱい。
2006/03/17(金) 13:58:49> 初心者の質問に、誰かが man嫁と回答してるのを見て、
> その直後にもっとずばりの回答をしてるのがオレ。
質問者が調べる機会を奪っちゃいかんよ。
0783名無しさん@お腹いっぱい。
2006/03/17(金) 14:25:41でもオマエmanの入れ方解らないで教えてもらったじゃん
0784名無しさん@お腹いっぱい。
2006/03/17(金) 16:11:110785名無しさん@お腹いっぱい。
2006/03/17(金) 17:15:070786名無しさん@お腹いっぱい。
2006/03/17(金) 21:56:29どのようにして、その先入観を打ち破る事が出来るのか。本当に悩ましい
0787名無しさん@お腹いっぱい。
2006/03/17(金) 22:14:27そのネタもう古い。もっと新しいの頼む。
0788名無しさん@お腹いっぱい。
2006/03/17(金) 23:57:090789名無しさん@お腹いっぱい。
2006/03/18(土) 00:07:220790名無しさん@お腹いっぱい。
2006/03/18(土) 00:18:150791名無しさん@お腹いっぱい。
2006/03/18(土) 12:04:50man入れるか入れないかは別として回答としては>>701が一番良いと思うけどな。
>>699の人はある程度調べた後に質問したように見えるし、調べる方向が間違いつつあるようにも見える。
そういう人にはそのものずばりの回答を出せば、その人は自分で man date で回答を確かめる事をすると
思うよ。
0792名無しさん@お腹いっぱい。
2006/03/18(土) 12:28:56だから?
要するに君はここが相変わらずレベル低いと言いたかったわけだね
0793名無しさん@お腹いっぱい。
2006/03/18(土) 13:22:42ジサジエも飽きたから何か変わったUNIXを振ってくれよ
0795名無しさん@お腹いっぱい。
2006/03/18(土) 13:39:280796名無しさん@お腹いっぱい。
2006/03/18(土) 14:01:41#!/bin/sh
if [ $# -lt 1 ]; then
echo 'usage: manco YourAge' 1>&2
exit 1
fi
thisyear=`date +%Y`
year=`expr $thisyear - $1 + 16`
sudo date 01010000$year
echo 'Happy old year!'
man co
0797名無しさん@お腹いっぱい。
2006/03/18(土) 14:03:360798名無しさん@お腹いっぱい。
2006/03/18(土) 14:13:130799名無しさん@お腹いっぱい。
2006/03/18(土) 14:37:08ありがとうございます。
早速実行してみましたが、
53歳だと、dateの実行のところでエラーになって
16歳に戻れません。
53歳以上にも対応したUNIXを打つ方法はありませんか?
0801名無しさん@お腹いっぱい。
2006/03/18(土) 14:47:10典型的な自作自演の告白乙
ココではそんなお約束は書かなくてもおk
0802名無しさん@お腹いっぱい。
2006/03/18(土) 21:09:36俺は801では無い。
manは入れてない。
いつもずっぽり。
0803名無しさん@お腹いっぱい。
2006/03/18(土) 21:18:06これを、coding system = euc に変更したいので、
hexでエンコードされた「:」入りの日本語ファイル名をすべて
EUCに変換したいのですが、
どういうシェルを書いて、どういうUNIXを打てばいいでしょうか?
0804名無しさん@お腹いっぱい。
2006/03/18(土) 22:07:30http://www.samba.gr.jp/project/contrib/smbchartool.html
0805名無しさん@お腹いっぱい。
2006/03/18(土) 22:23:41それ、、、以前使ったら、シンボリックリンクも全部おいかけられて、
1つのファイル名を何度も何度もコード変換されて、全部の日本語
ファイルが化け化けになったw
0806名無しさん@お腹いっぱい。
2006/03/18(土) 23:07:48http://ftp.yz.yamagata-u.ac.jp/pub/network/samba-jp/tool/smbjcode/
のsmbjconv.plで、
find . -type f -exec mv {} `echo {} | /tmp/ss/smbjconv.pl hex euc` \;
0807名無しさん@お腹いっぱい。
2006/03/18(土) 23:14:32findの -execのところに ` ` 書いても期待通りに動作しないと思うぞ。
0808名無しさん@お腹いっぱい。
2006/03/18(土) 23:59:270809名無しさん@お腹いっぱい。
2006/03/19(日) 00:18:50うーん、795の意図を正確に処理したら、
子プロセスがたくさん出来て困るんですけど。
0810名無しさん@お腹いっぱい。
2006/03/19(日) 01:37:00実行されたらあるディレクトリがあるか調べて
そのディレクトリが存在していれば○○
存在していなければ停止
このようなシェルスクリプトはどう書けばいいのでしょうか?
できればbashとshの両方が知りたいです
0811名無しさん@お腹いっぱい。
2006/03/19(日) 01:47:49man test
0812名無しさん@お腹いっぱい。
2006/03/19(日) 04:34:39if [ -d あるディレクトリ ]
then
○○
else
停止
fi
0813名無しさん@お腹いっぱい。
2006/03/19(日) 06:04:35A = 'ps ax | grep あるディレクトリ | wc -l'
if [ $A ]; then
○○
else
停止
fi
0814名無しさん@お腹いっぱい。
2006/03/19(日) 06:05:20A = 'ls | grep あるディレクトリ | wc -l'
if [ $A ]; then
○○
else
停止
fi
0815名無しさん@お腹いっぱい。
2006/03/19(日) 09:02:40何がしたいんだ? >>812の正解のあとで間違った答えを出して
0816名無しさん@お腹いっぱい。
2006/03/19(日) 09:26:290817名無しさん@お腹いっぱい。
2006/03/19(日) 09:26:39君も man test
0818名無しさん@お腹いっぱい。
2006/03/19(日) 09:32:34>>812 正解。
>>813-814 初心者かな? >>812 の正解を参照汁。
それだとディレクトリがなくても wc -l の結果の 0 が Aに入るので、
ifで常に結果が真になる。grepでの判定も曖昧。
そんなことしなくても [ -d hoge ] でできることを覚えろ。
0819名無しさん@お腹いっぱい。
2006/03/19(日) 09:34:42おまえら一生manだけ読んでろ。manを読むばかりで手を動かさない机上の空論者だな。
0820名無しさん@お腹いっぱい。
2006/03/19(日) 09:40:23はぁ?
>>806 はfind実行する前に ` `が展開されるよ。
しかも、find の -exec のあとは直接のコマンドであって、
シェルスクリプトではないため、
-execの実行時には一切のシェルの解釈を受け付けない。
だから、仮に ` ` がfindの実行前に展開されていないとすると、
逆に -exec の時に ` ` がエラーになる。
いずれにしても、>>806 は大間違い。
俺は正解を知ってるが、回答者バトルのために敢えて書かない。
わかるモン居たら書いてみろ。
0821名無しさん@お腹いっぱい。
2006/03/19(日) 09:50:160822名無しさん@お腹いっぱい。
2006/03/19(日) 10:45:01熱くなりすぎ。>>808は>>807への突っ込みだと取ったんだが。
0823名無しさん@お腹いっぱい。
2006/03/19(日) 13:05:49それに突っ込んでる >>808 は間違い。
おおもとの >>806 が間違いなのは言うまでもないが。
0824名無しさん@お腹いっぱい。
2006/03/20(月) 12:00:36私英語苦手・・・・じゃなくて、日本語苦手。
0825名無しさん@お腹いっぱい。
2006/03/20(月) 14:43:210826名無しさん@お腹いっぱい。
2006/03/20(月) 16:27:410827名無しさん@お腹いっぱい。
2006/03/20(月) 16:36:01アンカー先間違えてる?
818にそう言っても話が繋がらないのだが・・
0828名無しさん@お腹いっぱい。
2006/03/20(月) 16:51:180829名無しさん@お腹いっぱい。
2006/03/20(月) 21:22:48カレントディレクトリ以下(サブディレクトリ含)にある.c,.cc,.cppのファイル数を知りたいのですが、どうしたらよいのでしょうか。
find ./* -name *.c | wc -l
をそれぞれの拡張子で、では無く、一発で3種類のファイル数を求める方法を知りたいです。
後、
./script < inputfile
と入力した時、inputfileの中身をscript内で使うにはどうしたらよいでしょうか。
./script 1 2
とやると$1に1、というようになりますが、ファイルに
1
2
とあり、そのファイルを入力として渡す時はどのようにして1や2を得るのでしょうか。
0830名無しさん@お腹いっぱい。
2006/03/20(月) 21:40:01Q1 何故、findの機能を調べようとしないんだ?
Q2 何故、そのスクリプトエンジンの機能を調べようとしないんだ?
0831名無しさん@お腹いっぱい。
2006/03/20(月) 22:28:060832名無しさん@お腹いっぱい。
2006/03/20(月) 22:33:50そういうお答えはご遠慮願います。
ちゃんとわかる方のみ、ご回答よろしくお願いします。
0833名無しさん@お腹いっぱい。
2006/03/20(月) 22:38:06一問目は、man shかman bashして、
パス名展開(Pathname Expantion) のところ読んでね。
0834名無しさん@お腹いっぱい。
2006/03/20(月) 22:44:35>>829 の1問目は、「一発で3種類のファイル数を(それぞれ)求める方法」
らしいから、それは shの「パス名展開」を読んでも解決にならないだろ。
0835名無しさん@お腹いっぱい。
2006/03/20(月) 22:47:220836名無しさん@お腹いっぱい。
2006/03/20(月) 22:48:35死ねよ。クズ。
0837829
2006/03/20(月) 22:49:10忠告ありがとうございます。
findの方は -o -name の追加でなんとかなりました。
ファイル入力の方、ファイル名がスクリプト内で取得可能ならexecでどうこう出来る、
というのを見つけたのですが、肝心のファイル名をどうやって知ればいいのかわからんです。
なんか検索ヒント下さい。
0838名無しさん@お腹いっぱい。
2006/03/20(月) 22:52:35「それぞれ」で無くてもよかったのだけど、その場合一発で出来るんですかね。
0839名無しさん@お腹いっぱい。
2006/03/20(月) 22:54:221問目:
「一発で」というならfindやシェルスクリプトでは無理。
3回もfindしたくないということなら、
近い方法として、
find . -name '*.c' -o -name '*.cpp' -or -name '*.cc'
の結果をシェル変数またはテンポラリファイルに一旦取り込み、
その内容を
grep '\.c$' | wc -l
grep '\.cc$' | wc -l
grep '\.cpp$' | wc -l
すればよい。
2問目:
./scriptの中で readコマンドで標準入力の内容が1行ずつ読み込める。
普通、while readみたいにして使う。
0840名無しさん@お腹いっぱい。
2006/03/20(月) 22:57:06「それぞれ」でなくていいなら、
find . -name '*.c' -o -name '*.cpp' -or -name '*.cc' | wc -l
で一発。
0841名無しさん@お腹いっぱい。
2006/03/20(月) 22:59:190842名無しさん@お腹いっぱい。
2006/03/20(月) 23:02:07使われてるって現実もあるし。微妙な所か。
0843829
2006/03/20(月) 23:12:56>>839
while read var
して$varを全部echoしてみたのですが、最初の値が0になっている。こういうものなの?
一つ目を無視すれば済むのだろうけど。
0844名無しさん@お腹いっぱい。
2006/03/20(月) 23:18:14おそらく、whileループの「外」でechoしてるんだろう、とエスパーしてみる。
while readする場合にはちょっと癖があって、
while文の部分がサブシェルで実行されるので、
varに値を入れても、
whileループを抜けると消えてしまう(←ちょっと不正確な表現)んだよ。
うまく工夫してそれを避けるしかない。
0845名無しさん@お腹いっぱい。
2006/03/20(月) 23:19:32find . \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' \) -exec basename {} \; | \
( c=0 ; cc=0 ; cpp=0 ; while read i; do case $i in *.c ) c=`expr $c + 1`;; *.cc) cc=`expr $cc + 1`;; *.cpp) cpp=`expr $cpp + 1`;; esac; done; printf '*.c = %d\n*.cc = %d\n*.cpp = %d\n' $c $cc $cpp )
長すぎたので途中で折り返してる。
てか1行で書く必要は無いのか?
0846名無しさん@お腹いっぱい。
2006/03/20(月) 23:20:04この場合は while readを使わずに、
set `cat`
で読み込め。
これで、引数で起動したのと同じように
そのまま $1 $2 ... に代入されるよ。
0847845
2006/03/20(月) 23:20:140848829
2006/03/21(火) 00:06:34なんかよく分からないけど0が消えました。
さっき全く同じコードの筈なんだけどな。
入力ファイルの頭が0だった、なんて事は無いです。
while read var
do
echo $var
done
で0無しで動きました。不安なので再現狙ってみます。
>>845
長いからスクリプト書いた方が とか
でも一行で書けるものなんだと驚いたのも確か
>>846
うまいこと行きました。便利ですねこれ。さんくすです。
みなさんありがとうございました
0849名無しさん@お腹いっぱい。
2006/03/21(火) 00:10:20ちょっと作ってみた
--
find . -type f | egrep '\.(c|cc|cpp)$' | \
rev | cut -d. -f1 | rev | sort | uniq -c | sort -nr
--
egrepの部分に集計したい拡張子追加してね。
■ このスレッドは過去ログ倉庫に格納されています