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

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

■ このスレッドは過去ログ倉庫に格納されています
0001うはwwwww2006/03/26(日) 00:56:22
シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>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 でトレースしましょう。
0637名無しさん@お腹いっぱい。2006/06/21(水) 17:13:38
>>636
それ以前に、その拾ってきた奴というのがバイトオーダーの問題で
環境によっては動かないはずだが。
0638名無しさん@お腹いっぱい。2006/06/21(水) 17:20:10
>>636
RubyかPerlでやれば?
0639名無しさん@お腹いっぱい。2006/06/21(水) 19:42:56
Solaris10=SunOS5.10
Solaris9=SunOS5.9
Solaris8=SunOS5.8
Solaris7=SunOS5.7
0640名無しさん@お腹いっぱい。2006/06/21(水) 19:49:59
solaris11$ uname -sr
Solaris 11
0641名無しさん@お腹いっぱい。2006/06/21(水) 20:15:43
Solaris11$ uname -sr
Linux 2.4
0642名無しさん@お腹いっぱい。2006/06/21(水) 20:41:14
Ruby >>>>>>>> シェル
0643名無しさん@お腹いっぱい。2006/06/21(水) 21:14:47
典型的なrubyデブロッパー
ttp://jp.rubyist.net/magazine/?0001-NoraTutorial#l10
0644名無しさん@お腹いっぱい。2006/06/21(水) 21:54:47
$ uname -sr
Darwin 8.6.2
0645名無しさん@お腹いっぱい。2006/06/21(水) 22:27:13
下請けにシェルスクリプトの作成を発注する予定です

放っておくとtcshのシェルスクリプトを書くような連中なので
tcsh/csh/zshのシェルスクリプトは禁止する予定なのですが、
ターゲットはSunOSなので放っておくとbash固有の機能を使いかねません。

ボーンシェルのシェルスクリプトの仕様を提示したいのですがどこかにあるでしょうか?
0646名無しさん@お腹いっぱい。2006/06/21(水) 22:57:51
ボーンシェルって何ですか? Bourneシェルとは違うものですよね?
0647名無しさん@お腹いっぱい。2006/06/21(水) 23:04:57
>>645
マシンも環境も同じにするのがプロの発注。
0648名無しさん@お腹いっぱい。2006/06/21(水) 23:25:53
俺の経験上ヘボな奴ほどcshスクリプトを書く割合が多い。
理由はわからぬ。
0649名無しさん@お腹いっぱい。2006/06/21(水) 23:34:17
仕様を提示したところでそんな連中が仕様に従うはずない。
現物(マシン+OS+sh)を貸し出してこれで動くようにしろ、
というのが確実。

で、cshで書いてしまうような外注は捨てて、
もっとマシな所に発注するのがもっとも確実。
06506452006/06/21(水) 23:40:59
下請けの技術レベルが低いのはそのとおりですが、
元請の弊社は発注元と下請けの間の調整もせず勝手にやってというのが
基本姿勢のクズ会社なのでどっちもどっちなのです。

ポータビリティは考えずに、動作するコーンシェルのバージョンを指定しようと思います。
0651名無しさん@お腹いっぱい。2006/06/22(木) 00:12:29
opengroup.orgに転がってるPOSIXのシェルの仕様でも渡したらどうよ?
…英語の仕様書が読めるわけもないか。
0652名無しさん@お腹いっぱい。2006/06/22(木) 04:08:14
下請けより645のレベルが心配
0653名無しさん@お腹いっぱい。2006/06/22(木) 09:36:23
>>648
ヘボじゃない奴はcshではスクリプト書きにくいのにすぐ気がついて書かなくなるから
当然の帰結じゃないか。
0654名無しさん@お腹いっぱい。2006/06/22(木) 09:44:09
ヘボじゃあに香具師が、foreach使いたいからcsh script
を使っているのはみたことがある。
0655名無しさん@お腹いっぱい。2006/06/22(木) 11:57:13
cshはいろいろヘボいけど、それを使いこなしてこそ熟練者
cshは恐くない
0656名無しさん@お腹いっぱい。2006/06/22(木) 12:00:51
俺はまんじゅうが恐い
0657名無しさん@お腹いっぱい。2006/06/22(木) 12:14:55
cshはいろいろヘボいので、それを廃絶してこそ熟練者
cshはUNIXの汚点
0658名無しさん@お腹いっぱい。2006/06/22(木) 12:47:42
>>655
それはチューリングマシンでCGIを書くことに匹敵するほど実りの無いこと。
0659名無しさん@お腹いっぱい。2006/06/22(木) 15:19:23
645はkshしらんの?
Solarisからむなら普通ksh
0660名無しさん@お腹いっぱい。2006/06/22(木) 15:21:57
>>659
>>650


ただし、「kshの同じバージョン」はSolaris以外では用意できないと思われ。
Linuxにあるksh(pdkshじゃなくてkshだよ)は、Solarisのkshとは
結構動作が違う。
0661名無しさん@お腹いっぱい。2006/06/23(金) 22:15:00
Linuxのkshがどうだろうと、Solarisで開発すればいいのでは
いまの下請けはLinux で開発すんの?
0662名無しさん@お腹いっぱい。2006/06/23(金) 22:26:58
そりゃ、Solarisみたいな古いOSじゃ動かないかもね。Linux使えよ。
0663名無しさん@お腹いっぱい。2006/06/23(金) 23:08:39
OpenSolarisから持ってくればいいんじゃない?
0664名無しさん@お腹いっぱい。2006/06/28(水) 17:24:43
2行以上連続する空行を1行に縮めるにはどうすればいいですか?
0665名無しさん@お腹いっぱい。2006/06/28(水) 17:32:07
cat -s
0666名無しさん@お腹いっぱい。2006/06/28(水) 17:43:33
>>665
できました. でも質問が間違ってました. 改めて
2行以上連続する空行は1行に縮め,
1行だけの空行はその行を削除するにはどうすればいいですか?
0667名無しさん@お腹いっぱい。2006/06/28(水) 18:03:34
awk '/^$/{if(++n==2){print}next}{print;n=0}'
0668名無しさん@お腹いっぱい。2006/06/28(水) 19:35:20
できました. ありがとうございます.
0669名無しさん@お腹いっぱい。2006/06/29(木) 21:00:43
>>666
sed -e "N; s/\n$//; /^$/{N; /^\n$/D;};"
0670名無しさん@お腹いっぱい。2006/06/29(木) 23:09:01
webサイトのサムネイル画像から画像本体を取り出そうとしてまして
アドレスの一部、"thumb” を "src" に。数字の最後の ”s”を除去
あとバナー除去のために、"thumb” を含まないアドレスを削除しようと考えています

http://xxx/thumb/1585427411s.jpg から
http://xxx/src/1585427411.jpg
http://xxx/ad/bar_1.jpg ←バナー画像

/bin/sh
sed 's/thumb\/(\d+)s/src\/$1/'

で置換はできたと思ったのですがうまくいきません。
sed 's/thumb/src/' のように単純な置換だとうまくいきます
バナー画像に関しては行の削除がわかりません
文法間違えてたりしますか?アドバイスお願いします

OSXのAutomatorでやってます
0671名無しさん@お腹いっぱい。2006/06/29(木) 23:15:49
/thumb/d
0672名無しさん@お腹いっぱい。2006/06/29(木) 23:20:48
s@thumb/\([0-9]*\)s@src/\1@
0673名無しさん@お腹いっぱい。2006/06/29(木) 23:23:33
このディレクトリのこんなかんじの名前のファイルがあったらこの処理をするってシェルスクリプトってどう書くのかなぁ

-----------
cd /root/work
if [ -f abc* ]; then
処理1
else
処理2
fi
-----------

こんな感じのやつ。
でも、こんなワイルドカードの使い方ってだめなんでしょ?
0674名無しさん@お腹いっぱい。2006/06/29(木) 23:38:52
>>673
ちょっとしかないなら
if ls abc* >/dev/null 2>&1; then
でどう?

マッチするファイルが何万個もある可能性のある状況で
正しく動くのを作るのはちと複雑かも
0675名無しさん@お腹いっぱい。2006/06/29(木) 23:38:58
>>672
綺麗に置換できました。ありがとお
0676名無しさん@お腹いっぱい。2006/06/29(木) 23:40:11
>>669
うちのFreeBSD 4.11-RELEASEの/usr/bin/sedだとうまく動かん。
あわててcygwinのGNU sedで試したら動いた。
こんなのうちだけか?
sedの何かって環境依存なのかな???(ファイル末のNの振る舞いとかか?)

ちなみに上の「動かん」ってのをkwsk書くと:
・入力が1行のみの時、それが空行かどうか関係なく、出力が全く空。(wcに渡すと0バイト)。
・ファイル末に連続する空行があった時、それに対応して出力されるべき1行の空行がでない。
(つまり出力の最後は空でない行になっている)
06776732006/06/29(木) 23:49:24
>>674
ありがと。やってみるよ。

最近、シェルスクリプト書かなきゃならないところに異動になって困ってるんだ。
また助けてね。
0678名無しさん@お腹いっぱい。2006/06/29(木) 23:58:10
その給料の何%かで助けるよ
0679名無しさん@お腹いっぱい。2006/06/30(金) 15:52:08
>>676
BSDのsedとGNUのsedとは当然違います。
前者は古きよきBSDの雰囲気を留めているが、後者は独自に機能拡張してる。
0680名無しさん@お腹いっぱい。2006/07/01(土) 15:44:05
もしそうなら全然上げないBSDの方が独自だと思うぞ。
何をもって独自と断定するかは難しいが。
0681名無しさん@お腹いっぱい。2006/07/06(木) 12:02:41
DSCN0001.jpg〜DSCN9999.jpgのファイルを全てtravel2006GW0001.jpg〜travel2006GW9999.jpgに変更したいのですが
これを実現するLinuxのシェルスクリプトはどう記述したらいいですか?
それと
travel2006GW0001.jpg
travel2006GW0002.jpg



のようにtxtに打ち出すのもお願いします

0682名無しさん@お腹いっぱい。2006/07/06(木) 12:15:49
mv DSCN0001.jpg travel2006GW0001.jpg
mv DSCN0002.jpg travel2006GW0002.jpg
〜(以下同様に9999まで)

echo travel2006GW0001.jpg >foo.txt
echo travel2006GW0002.jpg >>foo.txt
〜(以下同様に9999まで)

2以降は'>>'なのに注意せよ。
0683名無しさん@お腹いっぱい。2006/07/06(木) 12:22:40
ちょw
0684名無しさん@お腹いっぱい。2006/07/06(木) 12:26:59
>>681
rename DSCN travel2006GW DSCN*
0685名無しさん@お腹いっぱい。2006/07/06(木) 12:34:15
>>681
マジレスするよ。
Linuxのシェルということはbashでいいんだよね。
だったら↓

#!/bin/bash

rm -f list.txt

for ((n=1; n<=9999; n++)) {
 nnnn=`printf %04d $n`
 mv DSCN$nnnn.jpg travel2006GW$nnnn.jpg
 echo travel2006GW$nnnn.jpg >> list.txt
}
0686名無しさん@お腹いっぱい。2006/07/06(木) 12:50:27
マジレスうれしぃ!
0687名無しさん@お腹いっぱい。2006/07/06(木) 13:30:19
>>682
こういうのを自動生成しちゃって実行する方が
楽なときもあるな。
実際に何が行なわれてるかわかりやすいし。
0688名無しさん@お腹いっぱい。2006/07/06(木) 13:33:29
>>687
その自動生成スクリプトも >>685 をちょっと改造すればできる
0689名無しさん@お腹いっぱい。2006/07/06(木) 13:42:15
>>687
あーそういうのよくやる。俺の場合だと

awk 'END{for(i=1;i<=9999;i++){printf "mv DSCN%04d.jpg travel2006GW%04d.jpg\n",i, i}}' /dev/null|less

とかやって確認してから

awk 'END{for(i=1;i<=9999;i++){printf "mv DSCN%04d.jpg travel2006GW%04d.jpg\n",i, i}}' /dev/null|sh

だな。mvの起動回数とか考えると何回も使うものならperlか何かでちゃんと書くけど、
1回限りのワンライナーだと確認しながらやれるのでこの方が安心できる。
0690名無しさん@お腹いっぱい。2006/07/06(木) 13:44:31
>>685
list.txtはわざわざスクリプトで作らなくても、名前の付け替えがすんだら
lsの出力をファイルに書き出せばいいだけじゃないか。
0691名無しさん@お腹いっぱい。2006/07/06(木) 13:49:13
>>687-690

http://pc8.2ch.net/test/read.cgi/tech/1112553783/299-301
> もう用済みじゃぼけぇwww
だそうですよ。
0692名無しさん@お腹いっぱい。2006/07/06(木) 13:50:06
wget って保存先指定できないの?.wgetrcでも
いつも直前にcdしてたんだけど不便で
0693名無しさん@お腹いっぱい。2006/07/06(木) 13:53:33
>>692
↓みたいなラッパーを、wgetという名前のスクリプトで書いて
先にPATHが通った ~/binにでも入れとけば?

#!/bin/sh

cd hoge
wget "$@"
0694名無しさん@お腹いっぱい。2006/07/06(木) 13:55:22
wget -P (or --directory-prefix=hoge) ?
0695名無しさん@お腹いっぱい。2006/07/06(木) 13:57:19
>>693
釣り?
0696名無しさん@お腹いっぱい。2006/07/06(木) 13:58:30
>>693
マラマラご冗談を
0697名無しさん@お腹いっぱい。2006/07/06(木) 14:03:29
毎回-Pを指定するのがめんどくさければ、.wgetrcに書いとけ。

dir_prefix = STRING
Top of directory tree--the same as `-P STRING'.
0698名無しさん@お腹いっぱい。2006/07/06(木) 14:41:04
おおこりゃ便利
ありがとう
0699名無しさん@お腹いっぱい。2006/07/07(金) 22:32:59
no-ipの自動設定スクリプトなんですけど
http://www.rhythm-cafe.com/shell/GrammerMenu.aspx
ここを参考にしながら
#!/bin/sh
wget http://dynupdate.no-ip.com/ip.php
ip='cat ip.php'
old_ip='cat oldip'
if [$old_ip!=$ip]; then
wget http://dynupdate.no-ip.com/update.php?username=MailAddress&pass=PassWord&host=HostName&ip=$ip
fi
mv ip.php old-ip
#sh -x ./ddns.sh
+ cat ip.php
+ ip=203.138.29.123
+ cat oldip
+ old_ip=203.138.29.58
+ [203.138.29.58!=203.138.29.123]
[203.138.29.58!=203.138.29.123]: not found
なんてエラーがでてしまいます
OSはNetBSD3.0です
恐ろしく基礎的な質問で申し訳ありませんが宜しくお願いします
0700名無しさん@お腹いっぱい。2006/07/08(土) 00:22:45
if [$old_ip!=$ip]; then

if [ $old_ip != $ip ]; then

[ はただのコマンド名なので特別扱いはされません。

cat fooをcatfooと書いたらだめなのと同じ理由でだめです。

07016992006/07/08(土) 00:54:48
>>700
お答えしてくださってありがとうございます
なんとか起動できました
0702名無しさん@お腹いっぱい。2006/07/08(土) 15:15:05
foreach i (1 2 3 4 5 6 7 8 9)
touch $i
end
とか
for i in 1 2 3 4 5 6 7 8 9;do
touch $
done
みたいな感じで、ファイルを名前を問わず
沢山作るにはどうすれば良いのでしょうか?
0703名無しさん@お腹いっぱい。2006/07/08(土) 15:36:00
seq 1 100000 | xargs touch
0704名無しさん@お腹いっぱい。2006/07/08(土) 15:39:48
while true; do mktemp "$(date)-XXXXXX";done
0705名無しさん@お腹いっぱい。2006/07/08(土) 15:40:30
>>703
sh: seq: command not found
0706名無しさん@お腹いっぱい。2006/07/08(土) 16:54:27
jotでもなんでもいいじゃんかよ
0707名無しさん@お腹いっぱい。2006/07/08(土) 17:55:57
:>${RANDOM}
0708名無しさん@お腹いっぱい。2006/07/09(日) 02:42:09
seqもjotもないぜ > Solaris

yes '' | head -10000 | cat -nでなんとかなるが
0709名無しさん@お腹いっぱい。2006/07/09(日) 10:49:20
Solaris8とかだと yesもないな。
0710名無しさん@お腹いっぱい。2006/07/09(日) 11:23:32
>>709
csh -cf 'repeat 100 echo'
0711名無しさん@お腹いっぱい。2006/07/09(日) 14:06:00
perlcc -e 'print $_ . "¥n" for $ARGV[0] .. $ARGV[1] ' -o seq
して seq を作る。

# もちろん冗談
0712名無しさん@お腹いっぱい。2006/07/09(日) 17:28:55
>>709
zshが入っているだろ。
0713名無しさん@お腹いっぱい。2006/07/09(日) 18:50:08
ファイルを変数展開してから開くにはどうしたらよいでしょうか?

aaa.txt の中身が
------------------
${vvv}
------------------
という記述のときに

#!/bin/sh
vvv="VVVVV"
cat aaa.txt
とした場合

------------------
${vvv}
------------------
ファイルに書いてある内容がそのまんま表示される、これを
------------------
VVVVV
------------------
としたいのです。

要は↓と同じことをもっと簡単に出来る方法はあるかということなのですが
#!/bin/sh
vvv="VVVVV"
v_sed=`sed \'s/\${vvv}/\'\${vvv}\'/g\' aaa.txt`
## sed 's/${vvv}/'VVVVV'/g' aaa.txt
eval ${v_sed}
0714名無しさん@お腹いっぱい。2006/07/09(日) 19:27:16
一般的には、開いてからshに食わせるんだけど、
変数展開だけをファイルオープン前に済ませたいのか。
難しいね。shを自作しないといけないかも。
0715名無しさん@お腹いっぱい。2006/07/09(日) 20:01:02
eval echo `cat aaa.txt`
0716名無しさん@お腹いっぱい。2006/07/09(日) 23:42:56
evalって今一使い方が分からない
0717名無しさん@お腹いっぱい。2006/07/10(月) 06:54:08
使っているうちにわかる。
0718名無しさん@お腹いっぱい。2006/07/10(月) 08:11:54
使い方はわかるが変数が絡むとキモス
0719名無しさん@お腹いっぱい。2006/07/10(月) 08:59:36
変数からめないでeval使ってもつまんないだろ
07207132006/07/10(月) 09:11:44
eval echo `cat ですか〜
ありがとうございます
やりたい事が出来ました。
0721名無しさん@お腹いっぱい。2006/07/10(月) 12:54:40
それじゃファイルの中味に`rm -rf `とか入ってたらどーする...

あまりに危険すぎるよ...
0722名無しさん@お腹いっぱい。2006/07/10(月) 13:07:20
それはそうだが前提条件次第だな。
0723名無しさん@お腹いっぱい。2006/07/10(月) 22:12:57
readを使ったときに入力文字を * でマスクしてくれる方法はありませんか?
イメージとしては login 時の Passwd: のような感じです。

以下のようなスクリプトを書きたいのですが、人に説明しながらスクリプトを
実行したい場合、パスワードが見えてしまうのでなんとかしたいです。
(さっと思いついた例なので誤字文法ミスは見逃してください)

#!/bin/sh

echo "user: "; read user
echo "passwd: "; read passwd

expect -c "
expect \"login: \"
send \"$user\r\"
expect \"passwd: \"
send \"$passwd\r\"
"
0724名無しさん@お腹いっぱい。2006/07/10(月) 22:15:42
>>723
stty -echo
read passwd
stty echo
0725名無しさん@お腹いっぱい。2006/07/10(月) 22:41:59
うほ。できました。
無知は損ですね。ものすごく助かりました。

man sttyで-echoの意味を調べたところ、
echo (-echo)
Echo back (do not echo back) every character typed.
ということで、そのままecho backさせないということのようです。
ありがとうございました。
0726名無しさん@お腹いっぱい。2006/07/11(火) 01:02:22
>>723
read -s

たぶん bash 専用オプションだが。
0727名無しさん@お腹いっぱい。2006/07/11(火) 21:59:23
シェルスクリプトで、キーボードから値を入力させる時に、
デフォルト値を表示させておく事ってできるでしょうか?

例えば
入力しろやゴルァ>hogehoge■
としておいて、
ユーザがhogehogeの部分を編集できるようにしたいのですが。

シェルはshかcshかkshが使えるようです。
0728名無しさん@お腹いっぱい。2006/07/11(火) 23:02:11
編集ってのが良く分らんが、とりあえずreadlineが
使えりゃいいのかな。
07297272006/07/11(火) 23:46:11
まぁそうなんだが、
1.Cでの開発は無理そうだ
2.多分readlineやlibeditは入っていないし、入れることはできないだろう

ユーザから入力を求める際に、あらかじめ入力バッファ(?)に
文字を入れておくこととかできないのだろうか。
0730名無しさん@お腹いっぱい。2006/07/11(火) 23:54:17
普通

入力しろやゴルァ [hogehoge]>■

これが気に入らないなら頑張ってくれ。
07317272006/07/12(水) 06:07:57
気に入らないから頑張りたいんだけど、
頑張り方が分からない。
0732名無しさん@お腹いっぱい。2006/07/12(水) 08:05:53
bashのreadは-eすりゃreadline使うようだが、初期値を入れる方法が
みつからないね。もうCかperlかなんかでそういうコマンド用意する
しかないような気がしてきた。

perlだとこう。

use strict;
use Term::ReadLine;
my($prompt, $preput) = @ARGV;

my $term = Term::ReadLine->new('hoge');
my $s = $term->readline($prompt, $preput);
print $s, "\n";

使い方:
x=`perl readline.pl '入力しろやゴルァ>' 'hogehoge'`

しかしこのスレでperlのような飛び道具を使うのは気が引ける...
0733名無しさん@お腹いっぱい。2006/07/12(水) 08:32:46
いいじゃん、適材適所で。
0734名無しさん@お腹いっぱい。2006/07/12(水) 09:26:46
結論としては、やっぱスクリプト言語使えってことか。
言語の学習は手間暇かかるんだよね。時間も。できればシェルスクリプトで
済ませたい。
あー、俺がもっと頭良ければ、新しい言語ぐらいすぐに覚えるのに。
0735名無しさん@お腹いっぱい。2006/07/12(水) 09:32:02
シェルスクリプトであれこれ工夫するほうが、適当なスクリプト言語(perlとかrubyとかpythonとか)
おぼえるよりよっぽど頭使うと思う。
0736名無しさん@お腹いっぱい。2006/07/12(水) 10:32:28
UIに特化したdialog(1)もよろしく
■ このスレッドは過去ログ倉庫に格納されています