シェルスクリプト総合 その14
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
2009/01/29(木) 06:54:48スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
Linuxユーザは/bin/shの正体がbashなので特に注意。
FreeBSDユーザは/bin/shの正体がashなので注意。
v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。
http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/sh/
http://heirloom.sourceforge.net/sh.html
・csh/tcshのシェルスクリプトは推奨されません。
(理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
manや参考リンクを見ましょう。
aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
前スレ落ちたみたいなのでリンク省略。
0724名無しさん@お腹いっぱい。
2009/05/03(日) 21:26:12ぱっと見、怖いスクリプト書いてるな…
一般的な助言しとくと
・カレントディレクトリは明示的に指定しる。
・cron実行時のPATH環境はどうなってる?
(要はfindとrmコマンドは、フルパスでなくても実行可能?)
・このスクリプトに実行権与えてる?
0725名無しさん@お腹いっぱい。
2009/05/03(日) 21:57:18ご指摘ありがとうございます。カレントは「具象化」します。
実行エラーの原因がわかりました。
改行コードが「CRLF」でした _| ̄|○ il||l
「LF」のみして正しく動作しました。
0726名無しさん@お腹いっぱい。
2009/05/03(日) 22:45:14おおげさな「助言」が全く関係ないオチだったね。
エスパー失格。
0727名無しさん@お腹いっぱい。
2009/05/03(日) 23:10:48おまえ何様のつもり?
>>724の指摘内容は、cronでスクリプトが動かないときに
真っ先に疑うべき内容で、別に大げさな助言でもなかろうに。
善意で答えている人に対して失礼すぎ。
0728名無しさん@お腹いっぱい。
2009/05/03(日) 23:37:25指摘は当たらないと意味がない。
もっと >>723 の質問をよく見ろよ。問題の鍵はここにあるんだよ。
>>723 の 「find: missing argument to `-exec'」のエラーメッセージ。
これが大きな鍵だ。
試しに、
find . -exec echo {} ?^M
って実行してみると良い。^Mは、Ctrl-[V] + [M] の CR な。
find: missing argument to `-exec'
って出るだろ。
あと、>>723 の「: command not found」
これは、#!/bin/sh^M になってる時出るメッセージだ。
以上を知ってれば的確な答えはすぐに出せたはず。
0729名無しさん@お腹いっぱい。
2009/05/04(月) 00:28:45たとえば、
find . -type f -name \*php
と
find . -name \*php -type f
は、実行速度に違いとかありますでしょうか?
0730名無しさん@お腹いっぱい。
2009/05/04(月) 01:01:09選択性の高いものを先に書いたほうが早い。
例えば比率的に「ファイル数:ディレクトリ数=9:1」で「*phpの数:*php以外の数=1:9」なら -name \*php を先に書いたほうが、90%の確率で -type f を評価する必要がなくなるので、逆に書くよりは高速になる可能性が高くなる。
要は、対象になるディレクトリの中身がどうなる傾向にあるかに拠る。
ただ、-type f単体の評価のほうが-nameより高速であろうから、単純に比率だけからでは一概には言えない。実際に計測して統計とるのが最善。
0731名無しさん@お腹いっぱい。
2009/05/04(月) 01:01:140732名無しさん@お腹いっぱい。
2009/05/04(月) 06:14:41>>730は釣り。
0733名無しさん@お腹いっぱい。
2009/05/04(月) 09:02:34処理するつくりになってると思い込んでいるんだろう
そういう仮定(本人は仮定とは思ってない)が書かれないから、他人には
全く理解不能になってしまう。
0734名無しさん@お腹いっぱい。
2009/05/04(月) 11:06:23従って指定順に処理されると考えるのが普通。
>>733はエスパーしたいなら、エスパースレにいけ。放置された質問たまってるぞ。
0735名無しさん@お腹いっぱい。
2009/05/04(月) 13:24:43http://www.linux.or.jp/JM/html/GNU_findutils/man1/find.1.html
find は与えられたファイル名以下のディレクトリツリーを検索し、同じく与えられた評価式を左から右に向かって優先順位の高いものから評価する (演算子のセクションを見よ)。
評価式の結果が確定すると (and の左項が偽だったり、 or の左項が真だった場合など) 評価は終了し、引き続き次のファイル名が評価される。
0736名無しさん@お腹いっぱい。
2009/05/04(月) 14:18:220737名無しさん@お腹いっぱい。
2009/05/04(月) 14:45:250738名無しさん@お腹いっぱい。
2009/05/04(月) 19:50:010739名無しさん@お腹いっぱい。
2009/05/05(火) 00:38:14違ったらごめんw
0740名無しさん@お腹いっぱい。
2009/05/05(火) 06:57:49(変わらないケースもまれにある)
0741名無しさん@お腹いっぱい。
2009/05/05(火) 22:31:34どちらの言ってることが正しいか自分の環境でテストしてみたんだけど、
1回目のfindでは7秒かかってたのが、2回目以降では、0.5秒で検索できた。
これって、OSがfindの結果をキャッシュしてるってことかなぁ、、、
テストするために、そのキャッシュをクリアする方法ってある?
ご存知の方は教えてくださいm(_ _)m
0742名無しさん@お腹いっぱい。
2009/05/05(火) 22:36:20それ、find自体は関係なくて、OSのファイルシステム(またはブロックデバイス)の
キャッシュが効いてるのが原因。
キャッシュの影響をなくすひとつの方法は、
umountできるディレクトリなら、
findの直前に一旦umountして、mountして、その直後に1回だけfindを実行する。
次のfindの前にまたumount/mountする。ちょっと面倒だけど。
0743名無しさん@お腹いっぱい。
2009/05/05(火) 22:36:22time sh first.sh; time sh second.sh;time sh first.sh; time sh second.sh;time sh first.sh; time sh second.sh;
おれは、こうしゃうけどね
でも、キャッシュはしていないと思うけどね
0744名無しさん@お腹いっぱい。
2009/05/05(火) 22:37:160746名無しさん@お腹いっぱい。
2009/05/06(水) 13:37:32で、テスト結果は?
0747>>741
2009/05/06(水) 23:56:33改行多すぎてはれないので、二回にわけてはるね。
■前提条件
~$ uname -r
5.4-RELEASE-p6
~$ find . -type f | wc -l
30374
~$ find . -type d | wc -l
1130
~$ find . -type l | wc -l
445
~$ find . -type f -name \*php | wc -l
137
■テストの手順
(1) time find . -type f -name \*php
(2) shutdown -p nowした後、マシン起動
(3) time find . -name \*php -type f
(4) shutdown -p nowした後、マシン起動
(5) time find . -name \*php -type f
(6) shutdown -p nowした後、マシン起動
(7) time find . -type f -name \*php
0748>>741
2009/05/06(水) 23:57:41■結果
(1)
real 0m7.697s
user 0m0.181s
sys 0m0.261s
(3)
real 0m7.205s
user 0m0.207s
sys 0m0.238s
(5)
real 0m7.229s
user 0m0.187s
sys 0m0.258s
(7)
real 0m8.164s
user 0m0.199s
sys 0m0.243s
find . -type f -name \*phpより、find . -name \*php -type fのようがはやい。
■結論
オプションの並びをかえると、実行速度はかわる
0749名無しさん@お腹いっぱい。
2009/05/07(木) 01:03:510750名無しさん@お腹いっぱい。
2009/05/07(木) 03:47:590751名無しさん@お腹いっぱい。
2009/05/07(木) 04:25:05> /dev/nullしろよ。
それじゃreal timeが表示の時間測ってることになるだろ。
0752名無しさん@お腹いっぱい。
2009/05/07(木) 06:10:32stat(2)は減らない。
1回のstat(2)で、ファイル名とファイルタイプは同時に得られるから。
0753名無しさん@お腹いっぱい。
2009/05/07(木) 10:03:02GNU の ls や stat を使うように書かれたシェルスクリプトを実行するために、
alias ls='gls'
alias stat='gstat'
を設定した状態で実行したいんですが、シェルでセットしてもシェルスクリプト中では有効になりません。
0754名無しさん@お腹いっぱい。
2009/05/07(木) 10:29:17stat(2)でファイル名得られるってどういうOSですかあ?
0755名無しさん@お腹いっぱい。
2009/05/07(木) 10:55:10readdir()等でファイル名一覧が得られたあと、
-type f のオプションがあるかどうかにかかわらず、
findとしてはそのディレクトリのすべてのファイルについて
一旦 stat(2)を実行する。
(でないと、サブディレクトリかどうかとかの判断ができないから)
で、-type fオプションとかがあると、すでに実行済みの stat(2)の結果を
利用するから、stat(2)の実行回数は増えない。
0756名無しさん@お腹いっぱい。
2009/05/07(木) 11:10:07PATHの一番優先順位のところに自作のディレクトリでもつくって、通して、ls,statというファイル名をつくって
$ cat ls
#/bin/sh
gls $@
$ cat stat
#/bin/sh
gstat $@
みたいなことするんじゃないの?
即席なんでこういうのは、ダサ過ぎなのかもしれないけど
0757名無しさん@お腹いっぱい。
2009/05/07(木) 11:45:08> (でないと、サブディレクトリかどうかとかの判断ができないから)
ディレクトリの判定には、いきなりchdirしてみると言う方法も考えられるので却下。
0758名無しさん@お腹いっぱい。
2009/05/07(木) 11:47:34実際のfindではいきなりchdirはしないから却下
0759名無しさん@お腹いっぱい。
2009/05/07(木) 11:48:26bashがスクリプト中でalias使えるか知らないが、
#!/bin/bash
alias ls='gls'
alias stat='gstat'
. そのシェルスクリプト
0760名無しさん@お腹いっぱい。
2009/05/07(木) 11:49:17そのような実装のfindが無いことを証明出来るなら採用。
0761名無しさん@お腹いっぱい。
2009/05/07(木) 11:51:39いきなりchdirすると、それがディレクトリへのシンボリックリンクだった場合に困る。
(-followオプションを付けていないのにsymlinkをたどっては行けないから)
だからいきなりchdirする実装はあり得ない。
0762名無しさん@お腹いっぱい。
2009/05/07(木) 12:29:240763名無しさん@お腹いっぱい。
2009/05/07(木) 12:35:530764名無しさん@お腹いっぱい。
2009/05/07(木) 16:42:560765名無しさん@お腹いっぱい。
2009/05/07(木) 18:24:100766名無しさん@お腹いっぱい。
2009/05/07(木) 18:24:380767名無しさん@お腹いっぱい。
2009/05/07(木) 18:53:47ttp://www.youtube.com/watch?v=h2mnwAJJDxY
ttp://www.youtube.com/watch?v=bfEVoJhxPPE
0768名無しさん@お腹いっぱい。
2009/05/07(木) 23:15:48readdir()すると、
ファイル名とi-node番号だけじゃなくて、
struct direntの中でファイルタイプも返すUNIXがある。
e.g. FreeBSD
0769名無しさん@お腹いっぱい。
2009/05/07(木) 23:20:140770名無しさん@お腹いっぱい。
2009/05/08(金) 04:01:23お前ら、レベル高いな、、、
ぜんぜん、この話題ついていけねぇ、、、orz
どうやったら、そんな高いレベルになるのか教えてくれ。
何かお勧めの本とか。
0771名無しさん@お腹いっぱい。
2009/05/08(金) 06:55:30その場合はreaddir()だけでファイル名もファイルタイプも得られるから、
findの-nameや-type fの有無にかかわらず、結局stat(2)の回数は増えない、でFA?
0772名無しさん@お腹いっぱい。
2009/05/08(金) 07:38:55GNU findは#ifdefで、
ファイルタイプ返すreaddirに対応している。
0773名無しさん@お腹いっぱい。
2009/05/08(金) 13:50:32OJTって知っている?
ひたすら仕事をすればいいんだよ。
0774名無しさん@お腹いっぱい。
2009/05/08(金) 17:42:350775名無しさん@お腹いっぱい。
2009/05/09(土) 08:38:090776名無しさん@お腹いっぱい。
2009/05/10(日) 18:00:18doneは皆さん何と読んでいますでしょうか?
人によって、ダーン、ドーン、ドネ、ディーオーエヌイーなどと呼んでいるのですが、
専門家の方はどう読むのでしょうか?
0777名無しさん@お腹いっぱい。
2009/05/10(日) 18:07:04「ドーン」じゃ人名
0778名無しさん@お腹いっぱい。
2009/05/10(日) 18:23:180779名無しさん@お腹いっぱい。
2009/05/10(日) 18:52:14小学生乙。
0780名無しさん@お腹いっぱい。
2009/05/10(日) 19:04:30http://pc12.2ch.net/test/read.cgi/unix/1001358861/
0781名無しさん@お腹いっぱい。
2009/05/10(日) 19:09:450782名無しさん@お腹いっぱい。
2009/05/10(日) 19:25:120783名無しさん@お腹いっぱい。
2009/05/10(日) 19:53:43ボーンじゃなくてブールネが正しいって聞いたことがあるんだが。
0784名無しさん@お腹いっぱい。
2009/05/10(日) 20:22:03だーんって読んだら笑われるぞ
英語じゃないんだから
>>776
ドーンが正解です
ドンでもいいですよ
0785名無しさん@お腹いっぱい。
2009/05/10(日) 21:36:26denyもデニーですよね。
0786名無しさん@お腹いっぱい。
2009/05/11(月) 13:33:520787名無しさん@お腹いっぱい。
2009/05/11(月) 16:18:470788名無しさん@お腹いっぱい。
2009/05/12(火) 08:11:17i did it
done
アメリカ行って聞いて故意w
0789名無しさん@お腹いっぱい。
2009/05/12(火) 08:11:58>ドーンが正解です
>ドンでもいいですよ
それなら
dawn
だなwぷけら
0790名無しさん@お腹いっぱい。
2009/05/14(木) 02:26:34これに関連して、全てのマニュアルの英単語の数を計算し、多い順にソートしたいのですが、
いい方法はありますでしょうか?
(#使われている頻度が多い英単語から覚えれば、効率的かなと。。)
0791名無しさん@お腹いっぱい。
2009/05/14(木) 02:36:44lsのマニュアルだけなら、これでできるよ。
--------------------------------
~$ man ls | col -b > words.txt
~$ for word in `cat words.txt`; do echo $word; done > words2.txt
~$ sort words2.txt | uniq -c | sort -n -k 1 -r | head
138 the
69 is
40 a
39 to
38 of
38 file
36 The
34 and
33 in
25 are
--------------------------------
全てのマニュアルってことになるとどうするんだろ。
0792名無しさん@お腹いっぱい。
2009/05/14(木) 04:32:48zcat /usr/local/man/man{1..9}/*.gz | nroff | col -b > /tmp/manuals.txt
以下同じ。
0793名無しさん@お腹いっぱい。
2009/05/14(木) 05:04:44ハリポタでもなんでもいいけど、興味の有る映画とかの本のほうが勉強に成ると思う。
0794名無しさん@お腹いっぱい。
2009/05/14(木) 06:18:10> ハリポタでもなんでもいいけど、興味の有る映画とかの本のほうが勉強に成ると思う。
ノベライズ(小説)は、難しいと聞くなあ
あと読んで(input)、誰かに書いて(output)ってしにくそう
コンピュータ(例えば、Linux)分野寄りの話なら、最初は大変だけど、メーリングリストに投げるなり、フォーラムに投稿するなり
できるし、書いた英文が不適切でも、コマンドと標準出力、エラーログを添付すれば、意味は通じるからね
コンピュータ寄りだけど英語の勉強になるし、楽しいよ
リスニングに関しては、海外ドラマDVDを家にいるときは字幕なしで流しっぱなしにしているのがいい感じ
単語がわからなくても、表情や動作で意味が伝わってくるからね
映画は連続ドラマに比べて、映画の性質上、無駄なくシーンがポンポン変わるからちょっときつい感じ
>>790
聞いてみるもんだね、簡単にできるんだね
0795名無しさん@お腹いっぱい。
2009/05/14(木) 06:32:55ノベライズは小説化だよ。
0796名無しさん@お腹いっぱい。
2009/05/14(木) 06:34:11シェルスクリプトのスレなんだからシェルスクリプトで答えればいいんだよ。
英語の勉強法なら別の板なりスレなりに誘導すればいいだけじゃないか。
0797名無しさん@お腹いっぱい。
2009/05/14(木) 06:49:22中間ファイル作るの無駄過ぎ。一発でできる。
man ls | col -b | tr ' ' '¥n' | tr '¥t' '¥n' | sort| uniq -c | sort -nr
0798名無しさん@お腹いっぱい。
2009/05/14(木) 06:53:30/var/wwwの、PHPの過去1日分の変更点だけのバックアップを取りたいのですが
-------------------------------
#!/bin/sh
dest=/var/www_bk/`date +%F`
mkdir $dest
chmod 777 $dest
find /var/www -mtime -1 -name "*.php" -exec cp -arp {} $dest \;
-------------------------------
これだと、フォルダの構造もなく、同一ファイルも重なってしまうためうまくありません。
(せいぜい-bつけるぐらい)
-------------------------------
#!/bin/sh
dest=/var/www_bk/`date +%F`
mkdir $dest
chmod 777 $dest
find /var/www -mtime -1 -name "*.php" -exec cp -arp {} $dest{} \;
-------------------------------
これだと「そんなフォルダねーよ」と蹴られてしまいます。
フォルダの階層ごとコピーがしたいですが、何か方法はありますでしょうか?
0800名無しさん@お腹いっぱい。
2009/05/14(木) 11:14:51Cron
-------
rsync -auvz --delete /var/www /media/disk-1/www-backup
-------
世代バックアップってできましたっけ?
0802名無しさん@お腹いっぱい。
2009/05/14(木) 11:34:430803名無しさん@お腹いっぱい。
2009/05/14(木) 11:40:09trを2個も重ねるの無駄過ぎ。一発でできる。
man ls | col -b | tr ' ¥t' '¥n¥n' | sort | uniq -c | sort -nr
0804名無しさん@お腹いっぱい。
2009/05/14(木) 12:03:06tar cf - `find ... -print` | (cd $dest; tar xpf -)
みたいなのはどうだろうか?findの結果が多い場合は`...`やめて-Tで
ファイル渡しで。
0805名無しさん@お腹いっぱい。
2009/05/14(木) 12:19:08ヒントだけ書くけど、
-exec cp -arp {} $dest{} ?
の前に、
mkdir -p `dirname $dest{}`
を実行すればいい。
find の -execに直接書くのはややこしいので、
ここだけ別のスクリプトにして、-execから呼び出した方がいいかも。
あと、cp -a オプションは、-pも-rも含んでるので、
cp -arp なんてやっても cp -a と同じだよ。
0807名無しさん@お腹いっぱい。
2009/05/14(木) 13:33:32find /var/www -mtime -1 -name "*.php" | cpio -pumd $dest
0808名無しさん@お腹いっぱい。
2009/05/14(木) 13:37:32ファイル名が改行などの特殊文字含む可能性がある場合はGNU cpioで
find /var/www -mtime -1 -name "*.php" -print0 | cpio -0 -pumd $dest
むう・・dirnameが走らない・・・
find /var/www -mtime -1 -name "*.php" -exec mkdir -p `dirname $dest{}` \;
なんか根本から間違ってる気がした
・・・でも
-----------
>>808
#!/bin/sh
dest=/var/www_bk/`date +%F`
mkdir $dest
#find /var/www -mtime -1 -name "*.php" -exec mkdir -p `dirname $dest{}` \;
#find /var/www -mtime -1 -name "*.php" -exec cp -a {} $dest{} \;
find /var/www -mtime -1 -name "*.php" -print0 | cpio -0 -pumd $dest
#tar cf - `find ... -print` | (cd $dest; tar xpf -)
chmod -R 777 $dest
-------
これで確かにいけました
なぜアーカイブが存在しないのにcpioが動くのか・・・
よ・・よくわからねーが、そのうち質問者は考えるのをやめた
0810名無しさん@お腹いっぱい。
2009/05/14(木) 14:00:12> コピーパスモードでは、 cpio はファイルをあるディレクトリから別のディレ
> クトリにコピーします。実際に は、アーカイブファイルを用いて、コピーア
> ウトモードとコピーインモードを 組み合わせて実行するような形になります。
> cpioは、コピーするファイルリストを標準入力から受けとります。これらの
> ファイルのコピー先のディレクトリについては、オプション以外の引数で与え
> られ ます。
ありがとうございました!
0812名無しさん@お腹いっぱい。
2009/05/14(木) 16:25:34http://pc11.2ch.net/test/read.cgi/linux/1238764663/
シェルスクリプト総合@LINUX Part5
0813名無しさん@お腹いっぱい。
2009/05/15(金) 18:34:05このシェルをTELNeTに関連付けるにはどうしたらいいですか?
毎回シェルのKEYINが必要なのですか?
0814名無しさん@お腹いっぱい。
2009/05/15(金) 18:49:38宣伝したいならvectorにでも行って登録しなさい。
0815名無しさん@お腹いっぱい。
2009/05/15(金) 19:08:260816名無しさん@お腹いっぱい。
2009/05/15(金) 19:11:57どうにもならんな
0817名無しさん@お腹いっぱい。
2009/05/15(金) 19:38:17How can I associate this shell with TELNeT ?
Do I need to KEYIN for shell every time ?
0818名無しさん@お腹いっぱい。
2009/05/15(金) 19:42:26このシェルはどうすればTelnetを関連付けることができますか?
私は毎回KEYINシェルのためには必要ですか?
0819名無しさん@お腹いっぱい。
2009/05/15(金) 20:10:360820名無しさん@お腹いっぱい。
2009/05/15(金) 20:19:440821名無しさん@お腹いっぱい。
2009/05/15(金) 22:14:520822名無しさん@お腹いっぱい。
2009/05/16(土) 03:55:450823名無しさん@お腹いっぱい。
2009/05/16(土) 08:21:23■ このスレッドは過去ログ倉庫に格納されています