トップページunix
1001コメント301KB

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

■ このスレッドは過去ログ倉庫に格納されています
0001ミスターシェル2006/09/07(木) 13:00:11
シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。


□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashなので特に注意。
・csh/tcshのシェルスクリプトは推奨されません。
(理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
 manや参考リンクを見ましょう。
 aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)

□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
0607名無しさん@お腹いっぱい。2006/12/16(土) 18:26:39
兄者!たすけておくんなせぇ

バックアップを1日3回取りたいのですが
日付毎のディレクトリを作って

mkdir /bak/`date +%d%m`

と、ここまではいいのですが2回目に、このスクリプトが動くと
もうディレクトリあるぞ( ゚Д゚)ゴルァ!!とエラーがでます(たいしたことはないのですが)

ディレクトリー作成とバックアップ用のスクリプトは別けたほうが良いでしょうか
if で あるからもう作らない 次進めとやると
速度落ちますよね?
なんかいい知恵ないでしょうか?
0608名無しさん@お腹いっぱい。2006/12/16(土) 18:30:13
>if で あるからもう作らない 次進めとやると
これでいいじゃんw
0609名無しさん@お腹いっぱい。2006/12/16(土) 18:38:48
ごめんなさい ひらめきました
cronで夜中ディレクトリ作ればいいのですね

>>608 if で毎回やるのがなんかイヤな感じがしたので
識者の方々に伺おうと思ったww
今は反省している

それと%m%d だよな 
逝って来ます
0610名無しさん@お腹いっぱい。2006/12/16(土) 18:41:48
つ mkdir -p
0611名無しさん@お腹いっぱい。2006/12/16(土) 18:56:56
>>610 それも考えたのですが。。。なんか毎回それを入れるのも・・・・・・
別に中身は消えないんでしょうけどww
なんか気持ち悪いorz

すんませんありがとでございます
0612名無しさん@お腹いっぱい。2006/12/16(土) 23:09:40
>>607
「ディレクトリがなかったら作る」でいいんじゃないの?
こんな感じ↓でやれば、1行で済むじゃん。

[ ! -d ディレクトリ ] && mkdir ディレクトリ
0613名無しさん@お腹いっぱい。2006/12/16(土) 23:57:53
たまには || の事も思い出してあげてください
0614名無しさん@お腹いっぱい。2006/12/17(日) 01:06:26
test のオーバーヘッド(w が気になるのなら、

 mkdir dir 2> /dev/null

でおけ。
0615名無しさん@お腹いっぱい。2006/12/17(日) 14:11:54
藻前らなかなかできるな!!
基本を身に付けたいorz
0616名無しさん@お腹いっぱい。2006/12/17(日) 18:50:14
>>614
set -e
で不都合が生じるから減点。
0617名無しさん@お腹いっぱい。2006/12/17(日) 19:54:25
たまには || の事も思い出してあげてください

mkdir -p dir 2>/dev/null || :
0618名無しさん@お腹いっぱい。2006/12/17(日) 20:25:49
-p || || では?
0619名無しさん@お腹いっぱい。2006/12/19(火) 18:01:03
確かにコマンドを形で覚えて?いるのか
標準入出力を意識(理解?)していない人は多いね。

たとえば、tar cf - . | ( cd /xxx && tar xpvf - )  とかすると
"-" について9割くらいは見ていた人に聞かれるし簡単には
何をやっているか理解してもらえない。

後は、3>&1 とか使えば多少は幅広がるのにね。
0620名無しさん@お腹いっぱい。2006/12/19(火) 18:04:17
- が標準入出力を表すかどうかはコマンドによって違うんで
またちょっと別の話かと。
0621名無しさん@お腹いっぱい。2006/12/20(水) 06:17:18
でも解凍するときは zxvf 圧縮するときは zcvf みたいに覚えてて
それぞれのオプションの意味を覚えていないやつってのはいるよね

結局伸びない
0622名無しさん@お腹いっぱい。2006/12/20(水) 06:25:30
>>621
そんな奴おらんやろ〜
0623名無しさん@お腹いっぱい。2006/12/20(水) 07:40:37
FreeBSDのtarなら圧縮形式自動判定してxvfだけで展開できるしな。
0624名無しさん@お腹いっぱい。2006/12/20(水) 07:45:47
>>622
いるよ〜

>>623
paxもおすすめ
0625名無しさん@お腹いっぱい。2006/12/20(水) 09:08:53
jはbzipだろ
zはgzだろ
xは解凍
cは圧縮
vは状況表示
fはファイル指定

じゃ無かったかな。
man tar してません。
0626名無しさん@お腹いっぱい。2006/12/20(水) 09:22:56
きっと、おぼえていることにポイントがあるわけじゃなくてぇ
0627名無しさん@お腹いっぱい。2006/12/20(水) 09:26:12
lhaのオプション覚えてる人いてる?
普段はファイラから解凍や圧縮してたんでじぇんじぇん覚えてにゃ
0628名無しさん@お腹いっぱい。2006/12/20(水) 09:32:17
マニュアルを引ければいいんじゃね?
0629名無しさん@お腹いっぱい。2006/12/20(水) 09:48:15
マニュアルを脳にインストールする話じゃないのか?
0630名無しさん@お腹いっぱい。2006/12/20(水) 10:18:46
いや
その知識自体の価値ではなく、その人の性質というかそういうものについてだよね
0631名無しさん@お腹いっぱい。2006/12/20(水) 11:27:32
なんにせよスレ違いだ。
0632名無しさん@お腹いっぱい。2006/12/20(水) 13:42:15
結局は基本を覚えて延髄の反射で書けるようにしておけってことでしょうか?
あと正規表現モナーですか?
0633名無しさん@お腹いっぱい。2006/12/20(水) 19:39:44
>>600
月が替わったりすると無理じゃね?w
20061125
20061201
20061231
20070101

よく月の1日にはリセットだなw
0634名無しさん@お腹いっぱい。2006/12/20(水) 21:25:32
文末にw付けるとwwなんかwwwいいことでもあるのか?wwwwwwwwwww
0635名無しさん@お腹いっぱい。2006/12/20(水) 23:33:00
grep の -w オプションみたいなもんだな
0636名無しさん@お腹いっぱい。2006/12/21(木) 00:16:42
>>633
BSD系なら
T=$(($(date +"%s") - 86400*10))
DATE=$(date -r $T +"%Y%m%d")

Linux (というかGNU coreutils) なら
DATE=$(date -d '10 days ago' +"%Y%m%d")
0637名無しさん@お腹いっぱい。2006/12/21(木) 00:27:27
date -v -10d +%Y%m%d
0638名無しさん@お腹いっぱい。2006/12/21(木) 00:37:34
>>637
-vはFreeBSD限定のような気がする
0639名無しさん@お腹いっぱい。2006/12/21(木) 02:39:21
>>594
rm `ls -t /directory/*.log | tail -n +11`
なんて方法もあるかなと。
0640名無しさん@お腹いっぱい。2006/12/21(木) 08:04:44
>>639
それいけるのか?
1日に複数個ログはいても
0641名無しさん@お腹いっぱい。2006/12/21(木) 16:23:03
date は1日引くのができるんじゃないっけ?
ago だかなんかの引数で
0642名無しさん@お腹いっぱい。2006/12/21(木) 16:29:37
>>641
FreeBSDのdateは無理です
0643名無しさん@お腹いっぱい。2006/12/21(木) 16:36:30
FedoraBSDって無いんですか?
0644名無しさん@お腹いっぱい。2006/12/21(木) 18:41:38
kFreeBSDならあってもおかしくない気がするよな
0645名無しさん@お腹いっぱい。2006/12/23(土) 04:10:11
大量のファイルに対して、
foo *
というようなことをやりたいのですが、arg list too longというような
メッセージが出ます。
で、有名な
echo * | xargs foo
で解決と思いきや、xargsってARG_MAXを超えた引数については、fooを呼びなおすみたいですね。
fooは全てのファイルに対して1回だけ実行されないと困るんですが、何かいい方法はあるでしょうか?
0646名無しさん@お腹いっぱい。2006/12/23(土) 09:36:47
foo を改造するしかない
0647名無しさん@お腹いっぱい。2006/12/23(土) 09:45:32
>fooは全てのファイルに対して1回だけ実行
xargs でいいじゃん
0648名無しさん@お腹いっぱい。2006/12/23(土) 10:11:40
全てのファイル <-> それぞれのファイル
0649名無しさん@お腹いっぱい。2006/12/23(土) 10:27:41
>>645
1 fooをshell functionで書き直す。
2 arglist広げてシステム再構築。
3 fooを複数回実行されても困らないよう作り直す。
0650名無しさん@お腹いっぱい。2006/12/23(土) 10:31:37
まずはオナヌーして落ち着く
0651名無しさん@お腹いっぱい。2006/12/23(土) 11:34:05


 find ... | xargs tar cvf hoge.tar

で ARG_MAX にあふれたファイルだけ入ったアーカイブ作ったことある。

たぶん受け側のプログラムを標準入力からファイル一覧読むように
改造するしかない。
0652名無しさん@お腹いっぱい。2006/12/23(土) 12:20:28
>>647
欲嫁。
>xargsってARG_MAXを超えた引数については、fooを呼びなおす
0653名無しさん@お腹いっぱい。2006/12/23(土) 12:25:48
xargs -n 100 とかでおk、とかそういう話ではない?
0654名無しさん@お腹いっぱい。2006/12/23(土) 12:37:58
>>652
xargsでいいじゃん
0655名無しさん@お腹いっぱい。2006/12/23(土) 12:54:36
>>654
欲嫁。
>xargsってARG_MAXを超えた引数については、fooを呼びなおす
0656名無しさん@お腹いっぱい。2006/12/23(土) 13:05:47
>>645の書き方がいまいち曖昧なんだが
fooで同じファイルを二度処理するのはまずいってだけの話なら
xargsでいいんでないの?

一度のfooの実行で全ファイルを処理したいっつーんなら、
引数渡しでやるのは無理だわなそりゃ
06576452006/12/23(土) 13:58:06
色々レスありがとうございます。

書き方が悪かったですが、fooは複数回実行されると困るというよりも、
全ファイルのデータを読み込んだ上でまあ数値計算みたいなものなんですが、
計算を行いたいわけです。
一度に処理されないと意味がない、ということです。

>>653
これ試してみましたけど、-n 100000とかやってもARG_MAXの壁は越えられないんで駄目でした。

どうもfoo内でフャ@イル一覧を読b゙ように書き換bヲるか、再構築bチてことみたいbナすね。
0658名無しさん@お腹いっぱい。2006/12/23(土) 14:02:43
ガベージイン
ガベージアウト
0659名無しさん@お腹いっぱい。2006/12/23(土) 15:50:07
引数の個数に1万か3万の制限があったような
0660名無しさん@お腹いっぱい。2006/12/23(土) 15:58:38
xargsって言ってる奴あほ過ぎる
0661名無しさん@お腹いっぱい。2006/12/23(土) 16:19:21
だから >>651 だってのに。
受け側のプログラムが引数使わないように修正する以外に方法はないって。
0662名無しさん@お腹いっぱい。2006/12/23(土) 22:29:44
xargsは obsolete。別の意味でも使ってはいけない。
0663名無しさん@お腹いっぱい。2006/12/23(土) 22:44:11
また湧いた
0664名無しさん@お腹いっぱい。2006/12/23(土) 22:50:02
>>662
kwsk
0665名無しさん@お腹いっぱい。2006/12/25(月) 11:59:27
find . -exec foo {} \;
0666名無しさん@お腹いっぱい。2006/12/25(月) 12:02:43
>>665
0点
0667名無しさん@お腹いっぱい。2006/12/25(月) 12:06:06
>>665
100点
0668名無しさん@お腹いっぱい。2006/12/25(月) 12:16:32
良く読んでない奴多いね。
foo file1 file2 .... (すべてのファイル)
みたいに、1回だけで実行したいという質問なので、
>>665 は 0点。
0669名無しさん@お腹いっぱい。2006/12/25(月) 12:26:59
んなことはみんなわかってる
0670名無しさん@お腹いっぱい。2006/12/25(月) 13:13:18
* じゃないしな。
0671名無しさん@お腹いっぱい。2006/12/25(月) 17:00:20
foo のbinary ラッパーを書いて、main を直接呼び出す。

普通はプログラムを書き直すよな...
0672名無しさん@お腹いっぱい。2006/12/27(水) 19:02:58
汎化してGPLで公開すればよくね?
0673名無しさん@お腹いっぱい。2006/12/28(木) 02:21:04
ARG_MAXってシェルの制限ではなくてint argc, char **argvのホントの
上限なんだね。標準入力からN行読み込んでexecvpで直接渡すようなの
書いてみたら32768でアウト。

任意のコマンドのmainをフックして、単なる関数として渡すような形で
汎化しないと駄目だな。もっとも問題のプログラムが処理対象のリストを
標準入力から読んだほうがよほどいいと思うけど。
0674名無しさん@お腹いっぱい。2006/12/28(木) 08:02:05
(ものすごくつまらない)ネタだと思ってたらマジで汎化してGPLとかほざいてたのか
0675名無しさん@お腹いっぱい。2006/12/28(木) 17:30:54
いや検討まで含めてネタだろ

バカか?
0676名無しさん@お腹いっぱい。2006/12/28(木) 19:40:53
gdb でmain で止めて、

レジスタ渡し、あるいはスタック渡しの部分で、malloc()で上書き。

.gdbinit で、がんがん代入。

実行開始。

ってのは、どう?
0677名無しさん@お腹いっぱい。2006/12/28(木) 21:21:09
こんなこと書いてるうちに元コード直し終わると思うけど、
-Dmain=xmain して、別途 dlsym(h, "xmain"); で呼び出すとか。
mainをそのまま直接呼ぶ方法あるのかな?ptraceとか使える?
0678名無しさん@お腹いっぱい。2006/12/28(木) 21:27:02
変わったシェルを使ってるんですね
0679名無しさん@お腹いっぱい。2006/12/28(木) 22:49:41
#!/bin/sh

( cat <<EOFEOF
extern int printf(const char *,...);
main(int ac,char *argv[])
{
int i;
for(i=0;i<ac;i++)
printf("%d %s¥n",i,argv[i]);
}
EOFEOF
) | gcc -x c -
(
echo "b *main"
echo "run"
echo 'set $r3=3'
echo 'set *((char **)$r4) = "test1"'
echo 'set *((char **)$r4+1) = "test2"'
echo 'set *((char **)$r4+2) = "test3"'
echo 'set *((char **)$r4+3) = "test4"'
echo " c" ) | gdb ./a.out

(Mac OS X 限定...)
ってな感じで、symbol table がある場合は可能らしい。strip されている場合は、
entry point を根性で探してくれ。
0680名無しさん@お腹いっぱい。2006/12/28(木) 22:52:07
おっと、
  set $r4=(void *)malloc(1000)
とかで malloc() するのを忘れずに。
0681名無しさん@お腹いっぱい。2006/12/29(金) 11:23:43
独自rtld書いてmain呼び出す。
0682名無しさん@お腹いっぱい。2006/12/29(金) 12:24:23
stripされててもmainのオフセット位置はどのプログラムでも同じ(同じ
環境なら)だから、そちらで調べた値をreadelfで得たエントリポイント
アドレスに足せばgdbのブレークポイント設定位置が判るよ。

後は$espから引数にアクセスして書きかえればいい。
この一連の操作はシェルスクリプトにできるから、xargsで扱えない
例外状況の処理用ツールになる(かもしれない)。
0683名無しさん@お腹いっぱい。2006/12/29(金) 19:38:07
ファイルをそのパスを含んだファイル名にしてコピーしたいです。
例えば ./foo/bar/mbox を ./foo_bar_mbox にコピーしたい。

find . -type f -name mbox -exec cp {} `echo {}|tr '\/' '_'` \;
とかしても
cp: ./foo/bar/mbox and ./foo/bar/mbox are identical (not copied).とエラーになっちゃう。

スレ違いだったら誘導して
0684名無しさん@お腹いっぱい。2006/12/29(金) 19:46:12
>>683
シェルが先に ` ` を評価するから
実際に実行されるのは
find . -type f -name mbox -exec cp {} {} \;
になるな。
0685名無しさん@お腹いっぱい。2006/12/29(金) 20:11:47
for f in `find . -type f -name mbox`;do cp $f `echo $f | tr '\/' '_'`;done
0686名無しさん@お腹いっぱい。2006/12/29(金) 20:27:54
無理に one-liner にしなくてもいいんじゃね?
0687名無しさん@お腹いっぱい。2006/12/29(金) 20:30:28
find . -type f -name mbox | sed 'p;s,/,_,' |xargs -n2 cp
0688名無しさん@お腹いっぱい。2006/12/29(金) 21:24:58
ありがとん。
>>685の方法で出来た。
0689名無しさん@お腹いっぱい。2006/12/29(金) 21:30:16
ねーねー
このスレのまとめって無いのかなぁ
ここしばらくの話、めっちゃ勉強になるんですけど
0690名無しさん@お腹いっぱい。2006/12/29(金) 21:32:30
わざわざ別解書いた >>687 が不憫。
それ以前の問題で外してしまった >>686 はもっと不憫。
0691名無しさん@お腹いっぱい。2006/12/29(金) 21:36:01
/usr/fbin
0692名無しさん@お腹いっぱい。2006/12/29(金) 22:02:53
>>690
>>687はエラー出ちゃうんだよ。
どうも最初の/しか置換されなくて._foo/bar/mboxにコピーしようするの。
で原因なんだろうと調べてみてるんだけどわけわからん。
0693名無しさん@お腹いっぱい。2006/12/29(金) 22:13:46
>>689
まとめてクレクレ
0694名無しさん@お腹いっぱい。2006/12/29(金) 22:48:30
>>692
多分 sed の部分が間違っているんじゃないかな
検証してないけど
0695名無しさん@お腹いっぱい。2006/12/29(金) 22:49:13
sedのところで、g が抜けてる。
0696名無しさん@お腹いっぱい。2006/12/29(金) 23:55:59
#!bash2.04

echo "$(echo " $(echo "`echo "$(ps)"`")")"

ちょい大げさに書きすぎたけど、こんな感じのを見かけた
これはどんな決まりでトークンに切り分けてるのさ!!
0697名無しさん@お腹いっぱい。2007/01/01(月) 00:02:28
新年キタコレ
今年もよろ69
0698名無しさん@お腹いっぱい。2007/01/01(月) 01:30:45
よろむく?
0699名無しさん@お腹いっぱい。2007/01/01(月) 02:23:40
>>698
Yellow Mookだろ。
それくらい察してやってくれ。
0700名無しさん@お腹いっぱい。2007/01/02(火) 11:18:36
>>699
素で分からんかったorz
0701名無しさん@お腹いっぱい。2007/01/03(水) 19:21:38
4649?
0702名無しさん@お腹いっぱい。2007/01/03(水) 19:36:33
よろシックスナイン
0703名無しさん@お腹いっぱい。2007/01/09(火) 22:08:18
0704名無しさん@お腹いっぱい。2007/01/10(水) 15:53:22
find で得られたファイルを更新時間順で並べる方法があれば教えていただきたい。
0705名無しさん@お腹いっぱい。2007/01/10(水) 15:59:18
ls -t `find hoge....`
0706名無しさん@お腹いっぱい。2007/01/11(木) 20:32:03
それでいいのか…
失礼しました
0707名無しさん@お腹いっぱい。2007/01/11(木) 22:03:31
argument too long
■ このスレッドは過去ログ倉庫に格納されています