トップページunix
985コメント289KB

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

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2007/02/15(木) 14:28:44
シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>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 でトレースしましょう。

前スレ
シェルスクリプト総合 その7
http://pc10.2ch.net/test/read.cgi/unix/1157601611/
0429名無しさん@お腹いっぱい。2007/05/16(水) 02:00:50
一旦デコードしてからエンコードするのが確実だな
04302012007/05/16(水) 02:03:24
01.jpg 02.jpg 03.jpg 04.jpg ...

と沢山のファイルがあってfor文(じゃなくてもいいけど)により

convert +append 01.jpg 02.jpg 03.jpg out1.jpg
convert +append 04.jpg 05.jpg 06.jpg out2.jpg
...

というように、3つずつ抜き出して一気に処理したいのですが、どうすればいいのでしょうか?
0431名無しさん@お腹いっぱい。2007/05/16(水) 02:23:41
>>430
100個ずつとかだと別の方法を使うが、3個ずつならこんなもんか

#!/bin/sh
set -- ??.jpg
i=1
while :; do
case $# in
0) break;;
1) convert +append $1 out$i.jpg; break;;
2) convert +append $1 $2 out$i.jpg; break;;
*) convert +append $1 $2 $3 out$i.jpg; shift; shift; shift; i=`expr $i + 1`;;
esac
done
0432名無しさん@お腹いっぱい。2007/05/16(水) 02:27:07
set -- *.jpg
i=0
while [ $# -gt 0 ]; do
i=`expr i + 1` #式使えるならそれでも。
convert +append $1 $2 $3 out$i.jpg
shift 3
done

shiftの数引数ってBourne Shellでも使えるのかな。
使えないなら3回shift。
0433名無しさん@お腹いっぱい。2007/05/16(水) 02:27:49
ああ、ちょうど3の倍数になっていない場合は考慮してなかったな。
0434名無しさん@お腹いっぱい。2007/05/16(水) 02:28:55
ちょうど3の倍数になっていない場合はどうすんの?
0435名無しさん@お腹いっぱい。2007/05/16(水) 02:29:55
/dev/null とかで補完
0436名無しさん@お腹いっぱい。2007/05/16(水) 02:37:35
名前欄は無視でお願い
04374302007/05/16(水) 02:45:01
おお、夜食食べている間にこんなにもレスが
3の倍数になっていないときは私自身考慮してませんでいした。
431さんの set だけ使ったことがないのですが、とにかく
>431-435 で十分対処できそうです。
setも調べてみます
ホントにありがとうございます。





04384302007/05/16(水) 02:46:51
よく見たら432さんもsetありましたね。
とにかくありがとう
04394212007/05/16(水) 11:12:47
>>422
シェルスクリプトで難しいならperlを使ってもかまいません。

>>423
URLエンコーディングならアルファベットはそのままだと思うのですが、
アルファベットも16進数表示したいわけです。
pukiwiki のバックアップをローカルに落とすのに、
ファイル名を知りたいんです。
0440名無しさん@お腹いっぱい。2007/05/16(水) 11:21:18
>>439
pukiwikiスレあたりで「戻し方教えれ」って聞いた方がいいんじゃね?
04414162007/05/16(水) 23:44:33
ご返事いただきありがとうございます。

tail -f ログファイル名 | awk -f 手続きファイル

上記コマンドではawkによる整形結果を標準出力できる状態で、
さらにパイプでteeコマンドを実行してみましたがうまくログが
出力できませんでした。

名前付きパイプを作成し、オリジナルログの出力先を名前つきパイプにして
直接awkで名前つきパイプを標準入力状態にしても、tail -f のような画面に
標準出力はできますがファイルへのリダイレクトは無理でした。
難しいですねぇ。。
0442名無しさん@お腹いっぱい。2007/05/17(木) 00:48:16
tee の使い方間違ってるだけだろ
0443ウサチャソ2007/05/17(木) 00:52:02
>>441
tail -f をパイプすると、上手く動かないよ。
GNUのだとどうなんだろ?

「tail パイプ バッファリング」
でググると、それっぽい事いっぱいでてくるYO
0444名無しさん@お腹いっぱい。2007/05/17(木) 18:41:18
a.shに . b.sh として読み込まれるb.shが自分の名前がb.shであると知る方法はありますか?
0445名無しさん@お腹いっぱい。2007/05/17(木) 18:50:24
>>444
ない。
. で読む場合は $0もセットされないし。
0446名無しさん@お腹いっぱい。2007/05/17(木) 19:05:57
>>445
ありがとうございます。
あらかじめ埋め込んでおくしかなさそうですね…。
04474162007/05/17(木) 23:00:53
>>443
バッファの問題だったんですね。

通常のawkはやめて、gawkのfflush関数を使うことでうまくいきました。
ありがとうございました。
0448名無しさん@お腹いっぱい。2007/05/18(金) 19:10:57
シェルスクリプトでログインログアウトを自動化するにはどうしたらいいでしょうか?
もし良かったら数行のコマンドでレスお願いします。
0449名無しさん@お腹いっぱい。2007/05/18(金) 19:15:55
>>448
何をやりたいのかもうちょい詳しく。
04504482007/05/18(金) 19:59:20
>>449

1.現在rootでログイン中。
2.testユーザーでログインして何か作業をする。
3.そしてまたrootに戻る。

これを自動化したいです。
0451名無しさん@お腹いっぱい。2007/05/18(金) 20:03:21
>>450
su test 何か
もしくは
su - test 何か

違いについては man su 等を参照。
0452名無しさん@お腹いっぱい。2007/05/18(金) 20:30:15
>>451
間違ってるよ。man su 等を参照するべきなのはオマエ。
0453名無しさん@お腹いっぱい。2007/05/18(金) 20:59:46
>>450
sudoじゃダメなんか?
0454名無しさん@お腹いっぱい。2007/05/18(金) 21:30:20
>>448
testユーザで実行するバッチファイルを作っておいて、
  su - test -c バッチファイル
で実行しる。
0455名無しさん@お腹いっぱい。2007/05/18(金) 21:35:19
バッチファイル
バッチファイル
バッチファイル
バッチファイル
wwww
0456名無しさん@お腹いっぱい。2007/05/19(土) 00:37:47
ほんとうにloginしたいならexpectを使うとか
04574482007/05/19(土) 03:04:26
rootでログイン中
expectでsu - testとして
touch /home/test.txtを実行して
再度expectでsu - rootでrootになっても
/home/test.txtは作成されてませんでした
なぜでしょう?
0458名無しさん@お腹いっぱい。2007/05/19(土) 10:21:42
パーミッションじゃないの?
/homeにtestユーザは書き込めないんでは。
0459名無しさん@お腹いっぱい。2007/05/20(日) 04:33:32
質問。
11.22.33を
33.22.11に文字を反転させたい。
04604592007/05/20(日) 04:42:15
459は取り消し!
11.22.33を
a[0]=11
a[1]=22
a[2]=33
のように配列に代入したい。
よろしくお願いします。
0461名無しさん@お腹いっぱい。2007/05/20(日) 05:39:47
宿題でつか
04624592007/05/20(日) 06:19:25
宿題でつ
04634592007/05/20(日) 07:14:05
スレ汚してごめんなさいできまつた
0464名無しさん@お腹いっぱい。2007/05/20(日) 21:56:12
テキストファイルに、ファイルの場所がずらずら書かれていて

-----
/usr/local/etc/pussy001.jpg
/usr/local/etc/pussy002.jpg
/usr/local/etc/pussy003.jpg
     :
-----

そこに書かれているファイルを指定した場所に移動させたいんです。
で、こんな感じで動くスクリプトを書きたいなぁと考えているんですが

cat list.txt | grep jpg | mv.sh /work/pussy

この mv.sh の書き方が分かりません。

0465名無しさん@お腹いっぱい。2007/05/20(日) 22:02:27
>>464
mv `grep jpg list.txt` /work/pussy

で、一発。・・・で、pussyってww
0466名無しさん@お腹いっぱい。2007/05/20(日) 22:47:23
>465
残念ながら、ファイル名にスペースがあるとだめでした。
sh, tcsh, bashで試してみましたが、どれも同じです。
0467名無しさん@お腹いっぱい。2007/05/20(日) 23:18:02
>>464 の例では、ファイル名にスペースが入ってないじゃないか。
そういう条件は先に例に含めて書くこと。
ファイル名にスペースがある場合のやり方ももちろん知ってるが、
わざわざ教える気にならないので俺はパス。
0468名無しさん@お腹いっぱい。2007/05/20(日) 23:25:45
>>466
IFS='
' mv `grep jpg list.txt` /work/pussy
0469名無しさん@お腹いっぱい。2007/05/21(月) 00:42:01
(while read f; do mv "$f" dest/ ; done) < file

>>467
ファイルの長さを考慮しないgrep戦法しか提示しなかった奴が
そんな理屈をこねても見苦しいだけ。
0470名無しさん@お腹いっぱい。2007/05/21(月) 06:22:05
>>469
残念ながら、ファイル名に \ があるとだめでした。
0471名無しさん@お腹いっぱい。2007/05/21(月) 10:38:53
じゃあ諦めな。
0472名無しさん@お腹いっぱい。2007/05/21(月) 11:09:30
>>471
ファイル名の \ を考慮しないを考慮しないwhile read戦法しか提示しなかった奴が
そんな理屈をこねても見苦しいだけ。
0473名無しさん@お腹いっぱい。2007/05/21(月) 11:17:06
というか、>>469 って、元の質問の jpg で grepするの忘れてるじゃん。
テストだったら0点。
0474名無しさん@お腹いっぱい。2007/05/21(月) 11:25:38
でもテストじゃないよ。
0475名無しさん@お腹いっぱい。2007/05/21(月) 11:33:37
そういう香具師が、「それはケアレスミス。答えはわかってた」とか後で言うんだよな。
0476名無しさん@お腹いっぱい。2007/05/21(月) 11:37:45
なんでそんな完璧にこだわるんだろ。
質問者のヒントになればいいじゃん。
0477名無しさん@お腹いっぱい。2007/05/21(月) 16:16:07
低能同士、仲良く!
04784642007/05/22(火) 00:44:46
すみません、御礼が遅れました。
という訳で >465 >468 >469 全て参考になりました。特にIFS=〜は初めて
知ったので成程と関心しました。
この場をお借りして厚く御礼申し上げます。
0479名無しさん@お腹いっぱい。2007/05/22(火) 00:59:36
xargsは?

grep jpg list.txt | xargs -i mv {} /work/pussy
0480名無しさん@お腹いっぱい。2007/05/22(火) 12:09:35
>>479
空白が含まれているとダメだろ。
0481名無しさん@お腹いっぱい。2007/05/22(火) 14:28:33
grep jpg list.txt | tr '\n' '\0' | xargs -0 -i mv {} /work/pussy
0482名無しさん@お腹いっぱい。2007/05/22(火) 14:39:38
>>481
ファイル名に改行が含まれてるとだめだろw
0483名無しさん@お腹いっぱい。2007/05/22(火) 19:06:13
sudo find / -name '*pussy*' -exec rm -rf \{\} \;
0484名無しさん@お腹いっぱい。2007/05/22(火) 19:18:18
デリミタが改行なリストなんだから要素に改行は含められないんじゃ?
改行入りファイル名を考慮するならリストは改行文字以外で区切るべき
だと思う.
0485名無しさん@お腹いっぱい。2007/05/22(火) 19:20:20
ファイル名に改行を入れるアホなんてほっとけ(w
0486ウサチャソ2007/05/22(火) 21:00:22
試しに作ってみた。

% touch aaaa^Maaaa
% ls -lF
aaaa*--r-- 1 ウサチャソ users 0 5月 22 20:58 aaaa

表示バグってるよ…
0487名無しさん@お腹いっぱい。2007/05/22(火) 21:19:38
改行と復改の区別ができないお子様は犬... 以下略
0488ウサチャソ2007/05/22(火) 21:37:01
>>487
改行のみ入れるのは面倒臭かったんだスマソ
0489名無しさん@お腹いっぱい。2007/05/22(火) 21:57:27
>>488
$ touch 'aaaa
aaaa'

だろ。

$ > 'aaaa
aaaa'

でも可。
0490ウサチャソ2007/05/22(火) 22:14:31
CTRL+Vが楽だったんで、つい…

ちなみに、>>489 でも >>486 でもCygwinだと同じ表示。

-rw-r--r-- 1 ウサチャソ なし 0 May 22 22:10 aaaa?aaaa

今日始めて知った。
0491ウサチャソ2007/05/22(火) 22:15:58
あ゛っごめん、Cygwinは「--show-control-chars」が必要だった…。
スレ違いなんでもう消えます、スマソ
0492名無しさん@お腹いっぱい。2007/05/24(木) 20:33:53
質問します。

lsnrctl >>_EOF_
set log_file listener.tmp
RET=$?
if [ $RET -ne 0 ];then
logger -t loglog -p local1.notice "切り替えに失敗しました"
exit 1
fi
exit
_EOF_

という事をしたいのですがどうしてもsetコマンド以降エラーに
なってしまいます。
対処法を教えていただけないでしょうか?
0493名無しさん@お腹いっぱい。2007/05/24(木) 20:51:21
逆だ。
lsnrctl <<_EOF_
0494名無しさん@お腹いっぱい。2007/05/24(木) 20:55:16
あと、ヒアドキュメントの部分は、LSNRCTLのコマンドしか受け付けないぞ。
0495名無しさん@お腹いっぱい。2007/05/24(木) 21:23:10
すいません逆に書いてました。
やはりLSNRCTLコマンドしか受け付けないですか・・・
う〜ん、どうしてもLSNCTLの中でシェルスクリプトの処理の記述を
したかったのですが無理そうですね。
ありがとうございました。
0496名無しさん@お腹いっぱい。2007/05/28(月) 07:13:03
質問。
ファイルの最終から20行を削除したい。
どうしたらいいでしょうか?
0497名無しさん@お腹いっぱい。2007/05/28(月) 07:46:41
>>496
wc で数えて、head で切り出すぐらいしか考え付かない
0498名無しさん@お腹いっぱい。2007/05/28(月) 08:09:27
awk
0499名無しさん@お腹いっぱい。2007/05/28(月) 08:33:29
tac なんてLinuxでもないかぎり標準装備じゃない罠

cat file | tac | sed '1,20d' | tac
0500名無しさん@お腹いっぱい。2007/05/28(月) 12:43:49
無意味なcat出た
0501名無しさん@お腹いっぱい。2007/05/28(月) 14:05:40
tacが使えなければ sed '1!G;h;$!d' すればいいじゃない。
0502名無しさん@お腹いっぱい。2007/05/28(月) 15:55:05
cat!出た!cat出た!得意技!cat出た!cat!これ!cat出たよ〜〜!
0503名無しさん@お腹いっぱい。2007/05/28(月) 16:13:35
>>502
楽しそうだな
0504名無しさん@お腹いっぱい。2007/05/28(月) 18:27:43
俺は限界だと思った
0505名無しさん@お腹いっぱい。2007/05/29(火) 00:14:45
tail つかって最後から20行みれ
で、>>499しる
0506名無しさん@お腹いっぱい。2007/05/29(火) 00:58:13
基本的にサブシェルはshを新たに起動するよりは動作が軽いですよね?
0507名無しさん@お腹いっぱい。2007/05/29(火) 01:26:05
>>498
awkには入力ファイルの行数を保持する組み込み変数はないんじゃね?
だから、結局wcでカウントしないとダメだったり。
0508名無しさん@お腹いっぱい。2007/05/29(火) 01:47:08
は?

awk '{a[NR]=$0}NR>20{print a[NR-20]}'
0509名無しさん@お腹いっぱい。2007/05/29(火) 02:37:14
>>508 短くていいが、でかいファイル通すとメモリが…
0510名無しさん@お腹いっぱい。2007/05/29(火) 02:54:34
無理して一行でやるより、行舐めの回数が少ない方が好きだな。
0511名無しさん@お腹いっぱい。2007/05/29(火) 02:57:15
>>510 ワンパスだし。消費メモリを考えればいいと思うが。
0512名無しさん@お腹いっぱい。2007/05/29(火) 03:15:32
>>499
は論外。
0513名無しさん@お腹いっぱい。2007/05/29(火) 09:33:18
awk '{if (FNR>20) print a[FNR%20]; a[FNR%20]=$0}'
0514名無しさん@お腹いっぱい。2007/05/29(火) 10:12:43
20行分だけバッファして遅延して出力させて
ファイル末尾に到達したら終了させるとか。
0515名無しさん@お腹いっぱい。2007/05/29(火) 19:07:30
>>514
書いてみよう
0516名無しさん@お腹いっぱい。2007/05/29(火) 19:20:43
>>514
>>513 がやろうとした事(間違ってるがw)
0517名無しさん@お腹いっぱい。2007/05/29(火) 19:44:45
>>496
こういう場合、ed を non-interactive に使うのがいい。

最後20行ということは、$-19から $までだから、

echo '$-19,$d
w outfile
q' | ed infile

↑で桶。
0518名無しさん@お腹いっぱい。2007/05/29(火) 21:46:07
sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'
0519名無しさん@お腹いっぱい。2007/05/30(水) 08:58:50
>>516 間違ってる?
0520名無しさん@お腹いっぱい。2007/05/30(水) 19:17:11
質問なんですが・・

#!/bin/sh -

tmpfile=/tmp/program.$$
cat "$1" | tr ' ' '\n' > tmpfile

while read word
do
grep ${word} "$2" | いろいろと処理・・・
done < tmpfile

てな感じのスクリプトなのですが、
第一引数のファイル中に、例えば -i と言うような語があると
grep がオプションと解釈するのか何なのか、直後に while ループが
終了してしまいます。
'${'"$word"'}' だと grep には ${word} として渡されてしまいます。

何とかシェルを騙して grep に '-i' として渡す方法は無いでしょうか?

(渡す前に条件判断して先頭文字が - なら sed などで先頭に \ を
付加すると言うのも行けそうな気はしますが、出来れば余計なIFとか
変数とか無しで行きたいものです)
0521名無しさん@お腹いっぱい。2007/05/30(水) 19:35:35
grep -e
grep -
05225202007/05/30(水) 19:53:07
>>521

ありがとう。
シェルを騙さなくても grep の方で用意されていましたか、
良く考えりゃ当然ですね。
0523名無しさん@お腹いっぱい。2007/05/30(水) 21:22:55
オプション -- で、それ以降はオプションとは解釈しないってのは
結構な数のコマンドで使える。
05245202007/05/30(水) 23:07:09
>>523

ですね。

これまで -- なんて、はぁ?って感じでしたけど、
実に有用性が高いですね。
勉強になります。
0525名無しさん@お腹いっぱい。2007/06/02(土) 11:43:37
質問
インターネットに接続できるか試すコマンドってありますか?

やりたいこと
インターネットに接続できたら echo "できます"
インターネットに接続できなかったら echo "できません"
としたいです。
0526名無しさん@お腹いっぱい。2007/06/02(土) 11:59:13
インターネットとLANの区別をしなくていいのかな?
0527名無しさん@お腹いっぱい。2007/06/02(土) 12:05:24
多分、この程度の精度でOKなんだろ。

if ping -c 1 www.yahoo.com >/dev/null 2>&1; then
echo "出来ます"
else
echo "出来ません"
fi
05285252007/06/03(日) 03:05:39
>>562>>527
ありがとうございます
できればヤフーなどの特定のサイトに依存せず
確実にインターネットに繋がるかどうか判断したいです。
もし無理なら特定のサイトでも構いませんが
こういう場合通例としてyahoo.comを使うのが適切でしょうか?
■ このスレッドは過去ログ倉庫に格納されています