シェルスクリプト総合@LINUX Part3
■ このスレッドは過去ログ倉庫に格納されています
0001login:Penguin
2007/07/10(火) 23:17:13ID:qGthZdMEまあそれはそれとして、BASHウゼーとか言われる心配なく
平和にLINUX的スクリプト談義しましょうよ。
初めての自作スクリプト、自信ないから見てください。な初心者から
トリッキーな技を駆使した作品を披露したい、蘊蓄を語りたい上級者まで
いろいろな人に参加して頂けると嬉しいです。
perlやらPythonやらの話が混ざっても良いんでない?
【sed】シェルスクリプト総合@LINUX Part2【awk】
http://pc11.2ch.net/test/read.cgi/linux/1154578200/
http://pc8.2ch.net/test/read.cgi/linux/1121994321/
>>2-5あたりに色々と。
0043login:Penguin
2007/08/09(木) 08:01:28ID:NwjhxE+fhttp://www.nurs.or.jp/~asada/FAQ/UNIX/section4.4.html
0044login:Penguin
2007/08/09(木) 11:34:05ID:EHaDR+6/俺? $0で十分だと思うけど?
0045login:Penguin
2007/08/09(木) 21:51:00ID:8UsjPRp60046login:Penguin
2007/08/10(金) 18:42:50ID:hRezB52r#!/bin/sh
for i in "$@"
do
a="$(echo $i | nkf -w)"
mv $i $a
done
convmv は元の文字コードを指定しなきゃならないのが面倒なので。
良かったらどぞ。
004746
2007/08/10(金) 18:44:30ID:hRezB52r./myconvmv.sh *
とかで使える。
0049login:Penguin
2007/08/15(水) 18:16:19ID:oxw3opBU・同名ファイルが存在する場合は、
既に存在するファイル名を「ファイル名.1」へ変更し、
既にファイル名.1が存在しているのであれば、それをさらにファイル名.2へ変更し、、、(繰り返し)
というコピーシェルスクリプトがほしいんですが、
簡単な記述方法などがあったらおながいします。
0050login:Penguin
2007/08/15(水) 18:22:48ID:vI6OWTR9自分ではどこまでできたの?
005149
2007/08/15(水) 18:30:05ID:oxw3opBUmv とかのオプションでそんな機能ないかな〜と
調べている程度の状態です。
--------------------------------------------------
・同名ファイルが存在する場合は、
既に存在するファイル名を「ファイル名.1」へ変更し、
既にファイル名.1が存在しているのであれば、それをさらにファイル名.2へ変更し、、、(繰り返し)
--------------------------------------------------
この部分を数行で教えていただけるとありがたいでつ。
ループ処理が必要になるのはなんとなく予想がつくのですが、、、
0052login:Penguin
2007/08/15(水) 18:34:51ID:vI6OWTR9ファイルが何番まであるかを先にチェックして
番号大きい方から順に mv してくのが楽かな。
[ とか expr 使え。
0053login:Penguin
2007/08/15(水) 23:30:14ID:BP+0zqcaそんな自堕落な道を私は選びました。
0054login:Penguin
2007/08/16(木) 07:16:56ID:D/eLf54Q全部*.cppにするにはどういう風に書いたらよいのでしょうか?
mv *.c *.cpp
としてみましたがだめでした
どなたかお知恵を...
0055login:Penguin
2007/08/16(木) 07:57:42ID:Uoi1O64b0056login:Penguin
2007/08/16(木) 10:10:37ID:MWEjh3WBfor f in *.c; do mv "$f" "${f}pp"; done
0057login:Penguin
2007/08/16(木) 13:33:29ID:D/eLf54QThx,できますた!
0058login:Penguin
2007/08/23(木) 16:17:17ID:n9QZBMiJシェルスクリプトある?
0059login:Penguin
2007/08/23(木) 16:36:59ID:lPn22JjI0060login:Penguin
2007/08/23(木) 16:53:47ID:C+I5hIDu普通にwgetでダウンロードすればいいだけでは?
youtubeから簡単に落としたいとかであればyoutube-dlとかが便利。
0061login:Penguin
2007/08/24(金) 19:56:13ID:k2Yrnoknいくつかのディレクトリの中にあるファイルのそれぞれの名前を変数に入れたいんだけど、
files=ls dir* | sort
for i in files
do
done
みたいなことは出来ませんか?
要するに標準出力する内容を変数に入れたいだけなんだけど。
0062login:Penguin
2007/08/24(金) 20:25:50ID:iKvrTLai「コマンド置換」でぐぐってみ
0063login:Penguin
2007/08/24(金) 20:43:22ID:k2Yrnokn理解できました。どうもありがとりんこです。
0064login:Penguin
2007/08/26(日) 16:36:55ID:sDCP6Pahls ... | sort | while read i; do echo $i; done
とかも定番。
0065login:Penguin
2007/08/27(月) 08:44:07ID:mTK43/6/do
done
sortを挟むのは良くわからんが、単純にこんなんで済む話じゃね?
0066login:Penguin
2007/08/27(月) 18:32:24ID:Vup2OsE3それだとlsの時点ですでに溢れる
0067login:Penguin
2007/08/27(月) 20:04:00ID:5Y4ThyNx0068login:Penguin
2007/08/28(火) 00:17:04ID:Gt/lw90mA.PDFとかファイルが格納されてて
0KB〜150MBなら 「ne-yo」
500〜600MBなら 「OK」 とfile.txtを出力したいのでつが・・・・・
if,thenの繰り返ししかないでしょうかね?
0069login:Penguin
2007/08/28(火) 00:58:46ID:is4Tjxw40070login:Penguin
2007/08/28(火) 08:13:17ID:k11zEdxe$ du -s * | awk '{ print $2," ", ($1 > 10000 ? "ne-yo" : "OK") }'
条件文のところは自分で書き換えてくれ。
0071login:Penguin
2007/08/28(火) 09:07:28ID:LHhLJxDo0072login:Penguin
2007/08/28(火) 14:07:23ID:LHPFC9xp0073login:Penguin
2007/08/28(火) 16:21:13ID:N3nQTqrG# time = 0.1000000000000000E-01
0 0.0000000000000000E+00 0.9108669739482692E-01 0.2058642824721793E-04 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00
1 0.3175362884490020E+01 0.5150471547462544E+01 0.2241689225773500E-03 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00
# time = 0.2000000000000000E-01
0 0.0000000000000000E+00 0.9108669739482692E-01 0.8246429583076927E-04 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00
1 0.3176583636040012E+01 0.5152080697165893E+01 0.8959185481550624E-03 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00
2 0.1132676183258557E+01 0.5482797684864557E+01 0.1300893227929982E-03 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00
# time = 0.3000000000000000E-01
0 0.0000000000000000E+00 0.9108669739482692E-01 0.1858117181080544E-03 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00
1 0.3178027531327324E+01 0.5153971284976635E+01 0.2013740280923297E-02 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00
という形式で出力されるデータで、# time = 0.2000000000000000E-01からはじまって、# time = 0.3000000000000000E-01の手前までを切り出すスクリプトを教えてもらえないでしょうか。できればawk(perlかrubyでも構いません)で教えていただけるとありがたいです。
0074login:Penguin
2007/08/28(火) 16:31:19ID:kk6ZVe0Nつcsplit
0075login:Penguin
2007/08/28(火) 22:47:28ID:WiEkAmOgこんな漢字か。酔っているので合っているのかどうだか。
0.000000...の部分は付け足してクレイ
0076login:Penguin
2007/08/28(火) 23:05:57ID:WiEkAmOgあと仕様の意味が、#time=...から始まる一ブロックだけ出す(空行が出たらオシマイ)
という意味ならもっと単純になる
0077login:Penguin
2007/08/28(火) 23:48:14ID:Gt/lw90mawk の ? と : の使い方に感動
>>71-72 ls -lh とかでやろうとしたのは漏れ様も同じww
0078login:Penguin
2007/08/29(水) 12:08:46ID:NEtL1MxO>>75
さっそくにありがとうございます。
試してみます。
0079login:Penguin
2007/08/29(水) 22:41:00ID:4pERO676と違うファイルだということだけわかればいいので
わかりやすく比較する方法はありませんか?
diffのマニュアルみてもそれらしいのはないようで
0080login:Penguin
2007/08/29(水) 22:50:35ID:UIgvqpQIdiff -rq dir1 dir2 ではだめなの?
0081login:Penguin
2007/08/29(水) 22:51:26ID:N3MeiS9ehttp://www.gnu.org/software/diffutils/manual/html_node/Comparing-Directories.html#Comparing%20Directories
$ LANG=C diff -r dir1 dir2 | grep Only
とかである程度分かるかも。
0082login:Penguin
2007/08/29(水) 22:52:42ID:N3MeiS9e0083login:Penguin
2007/08/29(水) 23:16:46ID:9GyP78LH0084login:Penguin
2007/08/30(木) 01:02:14ID:F11xsKF5イメージ的には、こんなことがしたいんです↓
----------------------------------
hoge="1.3.37"
foo="1.11.12"
if [ "$hoge" -gt "$foo" ]; then
echo "OK"
else
echo "NG"
fi
----------------------------------
これだと、以下のようjにエラーになってしまいます。。。。
[: 1.3.37: bad number
NG
0085login:Penguin
2007/08/30(木) 04:22:00ID:GmS5dPb3foo="1.11.12"
hoge=`echo $hoge | gawk -F. '{print (($1*100+$2)*100)+$3}'`
foo=`echo $foo | gawk -F. '{print (($1*100+$2)*100)+$3}'`
if [ "$hoge" -gt "$foo" ]; then
echo "OK"
else
echo "NG"
fi
ピリオド区切りの数が固定(この場合は3)
ピリオド内の桁数が固定(この場合は1-2桁)
という条件付だけど。これらが不定なら、$1,$2,$3...を$iにして、
NFまでループさせればいいと思う
0086login:Penguin
2007/08/30(木) 07:19:55ID:QpfKAJKgoldv=1.11.12
newv=1.3.37
として
if [ `echo $newv -gt $oldv | sed 's/\.//g'` ]; then
echo OK;
fi
もしくは、
if [ `echo $newv.$oldv | tr . ' ' | xargs printf "%d%.3d%.3d -gt %d%.3d%.3d"` ]; then
echo OK
fi
あたりでどうかな。
0087login:Penguin
2007/08/30(木) 18:00:56ID:bHskgKzhrpmver ってのがある。
$ rpmver -v 1.3.37 1.11.12
RPM version 1.3.37 is lesser than version 1.11.12.
Vine,VineSeed の RPMS.main SRPMS.main にある。
他のディストリは知らないけど
パッケージが用意されてるかもしれない。
0088login:Penguin
2007/08/30(木) 23:05:03ID:nhWZyH15rpmver not found
うえーん。。。
0089login:Penguin
2007/08/31(金) 00:47:12ID:U99N+hxPLinux板だからbashでもいいよね。
#!/bin/bash
v2n () {
local IFS=.
set $1
echo -n $(($1 * 1000000 + $2 * 1000 + $3))
}
hoge="1.3.37"
foo="1.11.12"
echo $(v2n $hoge) $(v2n $foo)
if [ $(v2n $hoge) -gt $(v2n $foo) ]; then
echo "OK"
else
echo "NG"
fi
添削してぇ
009173ですが
2007/09/01(土) 22:39:45ID:uwRTp3HZ仕様はおっしゃるとおりです。
その際のスクリプトも教えてくだされば幸いです。
なお、他のスクリプトは現在のところ動作していません。わたしの知識不足なのだろうと思うのでもうすこし調べてみます。
#0は補ってはあるのですが...
ついでといってはなんですが、awkの本でおすすめの本などありましたら教えていただけませんか?
0092login:Penguin
2007/09/02(日) 04:19:30ID:WMH1r7G1オライリーの sed & awk
てかawkの本なんて何冊もないって。
0093login:Penguin
2007/09/02(日) 08:46:56ID:ToB27R8d大穴 awk 256 本
0094login:Penguin
2007/09/02(日) 20:47:44ID:VmAuZafy「正規表現」「連想配列」という二つのキモを学習するにふさわしい内容。
読み終わったあとも、巻末の関数一覧がずっと使える。未だに刷を重ねてるけど
愛用者もおおいんじゃない?
大して御本家3人の書いたawk本は内容が高度な上に散発的で、調べたいことが
すぐに出てこなくて使いにくい
>>91
>>76のがその仕様のスクリプトなんだけど。うまく動かないのは、スペースとかが
ちゃんとコピペされてないからなんじゃないの?
009573ですが
2007/09/02(日) 21:37:03ID:71yMDj2y本の紹介ありがとうございました。
>>94
気づきませんでした。すいません。スペースの問題などを再確認してみます。
またなにかあったら伺うかもしれません。よろしくおねがいします。
0096login:Penguin
2007/09/02(日) 21:40:05ID:QLbcFUyG0097login:Penguin
2007/09/02(日) 21:55:05ID:ToB27R8d0098login:Penguin
2007/09/02(日) 22:03:47ID:VmAuZafyそう。今の版じゃ改訂されてるのかもしれないが、俺の持ってるのだと
gawkをDOSに移植したjgawkとかいうのを下敷きにしていて、中には486を乗せたキューハチだと
スクリプトの速度が向上したとか、パイプの実行速度が遅いのはUNIXみたいな本物のパイプじゃないからとか、
そんな話題が満載
0099login:Penguin
2007/09/02(日) 22:04:37ID:QLbcFUyG0100>>84
2007/09/04(火) 00:34:58ID:3rxVdbk90101login:Penguin
2007/09/06(木) 08:15:09ID:33eRwNa2/data/ をTOPディレクトリとしますと
/data/hoge/
/data/piyo/
/data/moge/
等が帰ってくるコマンドです。で、この際 /data/hoge/direc/ みたいに、TOPディレクトリの
孫ディレクトリ以下は返さないで欲しいんです。TOPディレクトリの子ディレクトリのみを
返して欲しいのです。そして for TARG in command; do 処理; done のように
for文で1つ1つのディレクトリを処理したいのです。
それからもう1つ、指定されたディレクトリ以下の子ディレクトリの数を返すには
ls -l /data/ | grep ^d | wc -l
でいいのでしょうか?ディレクトリだと ls -l した時に必ず最初が dから始まるので
これでディレクトリのみがマッチして、後はwcでその行数を数えればいいかと思っているのですが
今の所これでちゃんと動作していますが、不具合が発生するようなケースは想定されますか?
ディレクトリの数も孫ディレクトリ以下は数えません(再帰処理しない)。
昨日 basename と言う便利なコマンドを知った程度のレベルの人間ですので
awk や sed 等の難しいコマンドはなるべく使わずに実現したいのですが、出来ませんかねぇ?
宜しくお願い致します。
0102login:Penguin
2007/09/06(木) 08:27:57ID:QTrKtnCGls -d /data/*/
0103login:Penguin
2007/09/06(木) 08:30:08ID:QTrKtnCG0104login:Penguin
2007/09/06(木) 08:31:55ID:33eRwNa2あっちゃー・・・・そんな簡単なコマンドでこんな素晴らしい出力が得られるんですか!
LinuxのCUIって本当に高機能ですね・・・素晴らしいです。本当にありがとうございます。
ls -l /data/ | grep ^d | wc -l
ってやるより
ls -ld /data/*/ | grep ^d | wc -l
ってやる方が良いのでしょうか?どんなファイルやディレクトリがあっても確実に動作するような
書き方をしたいのですが・・・。
0105login:Penguin
2007/09/06(木) 08:32:01ID:QFjDOBHfls -d /data/*|grep "^d"
0106login:Penguin
2007/09/06(木) 08:33:56ID:QFjDOBHf0107login:Penguin
2007/09/06(木) 10:26:24ID:QTrKtnCG> ls -ld /data/*/ | grep ^d | wc -l
なんで grep するんだ?
0108login:Penguin
2007/09/06(木) 11:58:40ID:rZQRUej8/data/../ もヒットするのが難点だけどな。ってかあれだ。つ「man ls」
0109login:Penguin
2007/09/06(木) 16:47:27ID:40ywKZW4求めてることが出来たのであればどんなコマンドでもいいけど
find の使い方も知っておいたほうがいいと思う。
> 不具合が発生するようなケースは想定されますか?
> ディレクトリだと ls -l した時に必ず最初が dから始まる
ディレクトリへのシンボリックリンクがあった場合の扱いをどうするか。
さらに言えばリンクの対象がどこにあるか
ln -s /data/A /data/B と ln -s /tmp/C /data/B の違いとか。
0110login:Penguin
2007/09/06(木) 16:55:32ID:QTrKtnCGでよかったか。
>>109
> find の使い方も知っておいたほうがいいと思う。
同意。
0111login:Penguin
2007/09/06(木) 17:08:55ID:ZccH/OF/101への課題?
0112login:Penguin
2007/09/06(木) 20:00:39ID:QTrKtnCGそれもあるし、単にめんどうだし。
0113login:Penguin
2007/09/07(金) 11:30:33ID:BZSReuYlfind /data -type d -maxdepth 1
0114109
2007/09/07(金) 17:14:59ID:NgwMB5/h二ヶ所で減点。
1) find の出力に TOPディレクトリ(/data 自身)も含まれてる。
>>101 を読むとTOPディレクトリそのものは不要だと思う。
2) GNU find version 4.2.27 だと -maxdepth の位置で warning が出た。
find: warning: you have specified the -maxdepth option after a non-option argument -type, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it). Please specify options before other arguments.
0115login:Penguin
2007/09/07(金) 17:35:19ID:BZSReuYlなるほど。非常に参考になった。
模範解答を頼む。
0116login:Penguin
2007/09/07(金) 17:39:52ID:aiZtBudzもう一回自分で書いてみたら?
0117login:Penguin
2007/09/07(金) 19:24:55ID:Txvf/Wl4shopt -s nullglob
for i in /data/{,.{[!.],.?}}*/
do ...
こんなんでいかが
0118login:Penguin
2007/09/07(金) 19:45:52ID:ezpNZgi5に似ている。
0119login:Penguin
2007/09/07(金) 20:30:25ID:BZSReuYlOK。これでどうだ?
find /home/* -maxdepth 0 -type d
0120login:Penguin
2007/09/08(土) 04:46:18ID:WlyFgm6n>>119
/home/.xxx/ とかが出ない。
* 使うなら find 使う意味ない。
0121login:Penguin
2007/09/08(土) 14:42:47ID:vllGfkN4>* 使うなら find 使う意味ない。
上下別々の回答なんじゃないの?
0122login:Penguin
2007/09/11(火) 03:08:21ID:997sWGjJ0123login:Penguin
2007/09/12(水) 11:40:47ID:EatE1MlGls *.dat > list.txt
なぜか走らん。
0124login:Penguin
2007/09/12(水) 17:16:53ID:A49nKXNq子プロセスとして(?)起動するシェルに -f が渡らないんだと思う。
/bin/sh -f hoge.sh とか
あらかじめ /bin/sh -f で起動したシェルで
./hoge.sh みたいにすると
-f が有効になる。
0125login:Penguin
2007/09/12(水) 17:21:21ID:EatE1MlGエラーで *.dat: ファイルもディレクトリもありません とでる
ワイルドカードが原因かと思ったけど、hoge*でも同様のエラー
シェルにしたら走らず、コマンドラインで直接投げたら走る
なんでだろ
0126124
2007/09/12(水) 17:27:12ID:A49nKXNq/bin/sh -f の -f がどんな意味かわかってる?
あと、シェルとシェルスクリプトはちゃんと区別したほうがいい。
0127login:Penguin
2007/09/12(水) 17:33:44ID:EatE1MlGコンソールがcshだった
0128login:Penguin
2007/09/12(水) 20:01:20ID:9HkBr7tDpasswd_Aのものだけを残すというようなことをしたいのですがどうすればよいでしょうか?
0129login:Penguin
2007/09/12(水) 20:12:55ID:nfcPR4Gc一行ずつ上から順に読んでパスワードファイルに書き込む
書き込んだらそのユーザー名を別ファイルに書き出す
その別ファイルにユーザー名がないことを確認してから
パスワードファイルに書き込めばよい
0130login:Penguin
2007/09/12(水) 22:19:22ID:qqfxe9V8if [ "`grep ^${t%%:*}: passwd_A`" ];then
continue
else
echo $t >>passwd_A
fi
done <passwd_B
0131login:Penguin
2007/09/12(水) 22:53:21ID:SML918nzawk -F: '{
t[$1] = $0;
}
END {
for (e in t)
print t[e];
}' passwd_B passwd_A
0132login:Penguin
2007/09/12(水) 23:49:46ID:lhLTsTba0133login:Penguin
2007/09/13(木) 21:53:28ID:8j1+julM20070109,170000,170000,167000,170000,4
20070110,168000,168000,168000,168000,10
20070115,171000,171000,163000,169000,500
を
2007/01/09,170000,170000,167000,170000
2007/01/10,168000,168000,168000,168000
2007/01/15,171000,171000,163000,169000
のように
YYYY/MM/DDと表示を変更する
最後の,からあとを削除してbbb.txtとして出力したいと思っています
どのようにすればいいものでしょうか
4文字目と5文字目の間に/を挿入するということがsedでできなくて悩んでおります
よろしくお願いいたします
0134login:Penguin
2007/09/13(木) 22:06:02ID:OVx1tSlg0135login:Penguin
2007/09/13(木) 22:08:03ID:G9V8Phhbグルーピングしたパターンは後で\1,\2で参照出来る。
\を忘れるなよ。
0136login:Penguin
2007/09/13(木) 22:09:20ID:G9V8Phhb0137login:Penguin
2007/09/13(木) 22:25:32ID:8j1+julMありがとうございます
gwakというのも勉強してみようと思います
0138login:Penguin
2007/09/13(木) 22:52:13ID:8j1+julMmanを見てみたら いろんなところで使用できそうです
本当にありがとう
0139login:Penguin
2007/09/13(木) 23:24:02ID:saILvvtfcatは要らんだろ。
0140login:Penguin
2007/09/14(金) 00:50:00ID:uh85VpLs0141login:Penguin
2007/09/14(金) 12:28:52ID:hH9EcwDJps aux | grep XXX | grep -v grep | awk '{print $2}' | kill
ではだめなのに
ps aux | grep XXX | grep -v grep | awk '{print $2}' | xargs kill
ではOKなのはなぜですか?
0142login:Penguin
2007/09/14(金) 12:34:24ID:18sjQ9F0kill って標準入力を受け付けないんじゃない。
ところで pkill XXX じゃだめなの?
0143login:Penguin
2007/09/14(金) 12:37:30ID:hH9EcwDJそうなのかなと思って
for p in $(ps aux | grep XXX | grep -v grep | awk '{print $2}'); do
kill "$p"
done
ってのもやってみたんですが、だめだったんですよ。
■ このスレッドは過去ログ倉庫に格納されています