シェルスクリプト総合 その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 でトレースしましょう。
0351名無しさん@お腹いっぱい。
2006/11/17(金) 10:38:58rm *
を実行したら、すべてのファイルが消えてしまいました。(rm *.*じゃないのに)
これって、シェルのバグじゃないでしょうか?
あと、消してしまったファイルを復活する方法を教えてください。
0352名無しさん@お腹いっぱい。
2006/11/17(金) 10:46:01>> あと、消してしまったファイルを復活する方法を教えてください。
バックアップから戻せばOK
0353名無しさん@お腹いっぱい。
2006/11/17(金) 11:51:49普通は「拡張子」なんて言わず単に「suffix」って言うし。
0354名無しさん@お腹いっぱい。
2006/11/17(金) 11:53:130355名無しさん@お腹いっぱい。
2006/11/17(金) 12:06:03突っ込み処が不明なんだが…
0356名無しさん@お腹いっぱい。
2006/11/17(金) 19:37:09拡張子の無いファイル名に一致するシェル表現かー
.loginのようにドットで始まるファイルは対象なのか対象外なのかむずかしい
0357名無しさん@お腹いっぱい。
2006/11/17(金) 19:43:00.loginとかは対象外だろ(つーか、cshの例出すなよ)
hoge.c hoge hage.c hage
↑がある時、hogeとhageだけ消したいということだろ。
そう言えば、拡張子なしのファイルに一致するワイルドカードって
シェルにはないんだな。DOSだと「*」で桶なんだけど。
0358名無しさん@お腹いっぱい。
2006/11/17(金) 21:19:060359名無しさん@お腹いっぱい。
2006/11/17(金) 21:22:54find . -maxdepth 1 \! -name \*.\* -delete
0360名無しさん@お腹いっぱい。
2006/11/17(金) 23:21:23シェルの中で、あるシェルを呼び出すことを考えています。
2つのシェルはカレントであれば、実行可能なんですが、
パスを変えて実行するにはどうすればよいでしょうか?
例:
# pwd
/home/hoge1
# ls ../hoge2
A.sh Z.sh
# cat ../hoge2/A.sh
#! /bin/sh
date
./Z.sh
# cat ../hoge2/Z.sh
#! /bin/sh
echo "Call OK!"
# ../A.sh
2006年 11月 17日 金曜日 23:15:46 JST
../A.sh: line 4: ./Z.sh: そのようなファイルやディレクトリはありません
0361名無しさん@お腹いっぱい。
2006/11/18(土) 00:21:05#!/bin/sh
pwd
0362名無しさん@お腹いっぱい。
2006/11/18(土) 00:44:52死ねよ
0363名無しさん@お腹いっぱい。
2006/11/18(土) 01:50:24rm `ls * | fgrep -v .`
ファイル名にスペースがあると不十分かもしれん。
0364名無しさん@お腹いっぱい。
2006/11/18(土) 05:10:01ありがたいのですが、意味がわからないです。
0365名無しさん@お腹いっぱい。
2006/11/18(土) 07:22:59実在する余計なファイルを削除するにはどうしたらいいでしょうか?
#必要なファイル100個とか
files="a.txt 1.html hoge.jpg"
#実在するファイル100+1個以上
e_files="1.html a.txt fuga.gif hoge.jpg"
0366名無しさん@お腹いっぱい。
2006/11/18(土) 09:42:33ディレクトリというのがUNIXにはあるんだけども。
>>365
試してないけどこんな感じで
contains () {
local x="$1"; shift
for i; do
[ "x$i" = "x$x" ] && return 0
done
return 1
}
for f in $e_files; do
contains "$f" $files || echo "rm $f"
done
0367名無しさん@お腹いっぱい。
2006/11/18(土) 11:00:01シェルってゆうな。クズ
0368名無しさん@お腹いっぱい。
2006/11/18(土) 12:01:09なんと呼ぶの?
0369名無しさん@お腹いっぱい。
2006/11/18(土) 12:07:06>>1嫁。クズ。
0370名無しさん@お腹いっぱい。
2006/11/18(土) 12:17:17ls ではディレクトリは出力されませんがな。
alias 付けてなければ。
0371名無しさん@お腹いっぱい。
2006/11/18(土) 12:26:34こんなんなるんだけど。
$ touch fff
$ mkdir ddd
$ touch ddd/fff
$ /bin/ls *
fff
ddd:
fff
$ rm `/bin/ls * | fgrep -v .`
rm: cannot remove `ddd:': No such file or directory
rm: cannot remove `fff': No such file or directory
$
0372名無しさん@お腹いっぱい。
2006/11/18(土) 12:42:51どうすればよいのでしょうか。
0373名無しさん@お腹いっぱい。
2006/11/18(土) 12:54:17ちょっとメッセージが違うけど、これでいけることがわかった。
ls|grep -v hoge|xargs -p -n 1 rm
0374370
2006/11/18(土) 12:58:27ああ、そういうことか。
>>370は変なツッコミだった。スマソ。
ls * だとディレクトリの下のファイルがでちゃうから ls -d * だな。
さらに、はじめからディレクトリを除外するとしたら
for x in `ls -d * | fgrep -v .`; do
if [ ! -d $x ]; then
echo $f
fi
done
かな
ls -d * | fgrep -v . | xargs file | fgrep -v 'directory' | awk -F: '{print $1}' | xargs rm
ってのもあるけど
0375名無しさん@お腹いっぱい。
2006/11/18(土) 13:19:33安直なやり方として、
rm `fgrep -v -f files e_files` # 最初は rm じゃなくechoで試す
ってのがある。
ただし、files と e_files は 1行1ファイルでリストされたものとして。
さらに、files の中に "hoge.jpg" があると、e_files に中にある "hogehoge.jpg" は
削除されないけど。
0376名無しさん@お腹いっぱい。
2006/11/18(土) 15:54:42よろしくお願いします。
http://www.forest.impress.co.jp/article/2006/11/15/windowspowershell.html
http://support.microsoft.com/kb/926140
0377名無しさん@お腹いっぱい。
2006/11/18(土) 17:30:16シェルとシェルスクリプトは別物だぞw
Z.shのところ絶対パスでやれ。
それだけだ。
0378名無しさん@お腹いっぱい。
2006/11/18(土) 17:32:260379名無しさん@お腹いっぱい。
2006/11/18(土) 17:33:39内容はfor文のループ変数に配列を代入することは可能なのか?ということです。
for STARTEND in "(1 100)" "(101 200)";do
START=${STARTEND[0]}
END=${STARTEND[1]}
echo -e "&Avestart\nAve_start=${START}/\n&Aveend\nAve_end=${END}/" > namelist/namelist${START}to${END}
done
なるスクリプトを書いてみたのですが、
./speccalc.sh: line 15:(1 100): missing `)' (error token is "100)")
なるエラーが出ます。
もしbashで配列を配列のまま代入するということが不可能であるとして、それ以外のシェルで配列のまま代入することが可能なものはあるのでしょうか?
あるいはもっと他のツールを使った方がよいのでしょうか?
教えていただけないでしょうか?
0380名無しさん@お腹いっぱい。
2006/11/18(土) 17:35:51hairetu=(a b c d e f d)
for i in ${hairetu[@]}
do
echo $i
done
exit 0
こんな感じか?
0381名無しさん@お腹いっぱい。
2006/11/18(土) 17:39:21違うだろ。複数の配列を for 文の要素として使いたいらしいが。
0382名無しさん@お腹いっぱい。
2006/11/18(土) 17:40:460383名無しさん@お腹いっぱい。
2006/11/18(土) 17:42:03配列をFor文のループ変数に使えるかってことじゃないのか?
0384名無しさん@お腹いっぱい。
2006/11/18(土) 17:46:260385名無しさん@お腹いっぱい。
2006/11/18(土) 18:01:27borne shellには配列などというデータタイプは無い。
0386名無しさん@お腹いっぱい。
2006/11/18(土) 18:02:55"borne shell"って何ですかww
0387名無しさん@お腹いっぱい。
2006/11/18(土) 18:13:33eval STARTEND=$i
START=${STARTEND[0]}
END=${STARTEND[1]}
echo $START, $END
done
キモい。ただでさえキモい bash でさらにこんなキモいことするのか。
0388名無しさん@お腹いっぱい。
2006/11/18(土) 18:22:48いんじゃないか。
こんなインチキしか思い付かなかった
perl -e 'foreach $a ([1, 100], [101, 200]) {
print "$a->[0] $a->[1]¥n";
}'
0389名無しさん@お腹いっぱい。
2006/11/18(土) 19:47:14evalを使えば何でも出来る。
0390名無しさん@お腹いっぱい。
2006/11/18(土) 19:51:450391名無しさん@お腹いっぱい。
2006/11/18(土) 20:13:24>>339
>>340
0392名無しさん@お腹いっぱい。
2006/11/19(日) 01:55:30みなさん早速にレスいただき恐縮です。外出しておりました。申し訳ありません。
質問したかったのは>>383さんが書かれたとおりです。
>>387さんが書かれたスクリプトでうまくいきました。ありがとうございました。
ところで、配列がサポートされているCシェル、Kシェル、Zシェルでは「for文(に相当する構文)のループ変数に配列を用いること」は可能でしょうか?
0393名無しさん@お腹いっぱい。
2006/11/19(日) 07:47:13ありがとうございます。
とりあえず片付いたらそれをテストしてみます。
0394名無しさん@お腹いっぱい。
2006/11/19(日) 09:28:12関数を作らず、変数を1個使ってうまくいきました。
0395名無しさん@お腹いっぱい。
2006/11/19(日) 15:33:55項目が1万越していたら終らない
0396名無しさん@お腹いっぱい。
2006/11/19(日) 20:32:30そういう状況で適用したい人は自分で考えるってことで。
0397名無しさん@お腹いっぱい。
2006/11/20(月) 17:41:38: ${VAR:="exit script because VAR is not set."}
と記述すると、VARに値が設定されていない場合に実行中のスクリプトを
終了させることが出来る、と書かれているのですがうまくいきません。
これはなぜなんでしょうか?わかる方教えてください。お願いします。
0398名無しさん@お腹いっぱい。
2006/11/20(月) 18:01:09なんていう本? そんな間違った本捨てて、別の買え。
正しくは、
: ${VAR:?"exit script because VAR is not set."}
0399397
2006/11/20(月) 18:43:53早速のレスありがとうございました。うまくいきました。
けっこう長い時間これで悩んでたので本当に助かりました。ありがとうございました。
ちなみに参考書は
「入門UNIXシェルプログラミング シェルの基礎から学ぶUNIXの世界」
です。他のところで聞いたらこれを勧められたのですがダメな本なのでしょうか…。
0400名無しさん@お腹いっぱい。
2006/11/20(月) 19:22:210401名無しさん@お腹いっぱい。
2006/11/20(月) 19:44:220402名無しさん@お腹いっぱい。
2006/11/20(月) 19:46:36のフォームで報告しときゃいいんじゃね。
0403名無しさん@お腹いっぱい。
2006/11/20(月) 21:19:03読んで調べるぐらいした方がいいぞ。
0404名無しさん@お腹いっぱい。
2006/11/21(火) 00:06:55最近シェルスクリプト始めたのですがわからないことが
あって困っています。
小数の比較ってどうすればできるんですか?
---------------------------------------
#!/bin/bash
if [ 0.0001 -ge 0.00001 ]
then
echo "success"
fi
---------------------------------------
という風に書いて実行するとinteger expression expectedが出てしまうんで
すけど、どうしたらいいのでしょうか?
0405名無しさん@お腹いっぱい。
2006/11/21(火) 00:21:31整数で比較する
0406名無しさん@お腹いっぱい。
2006/11/21(火) 00:26:08あきらめろ。
awkやperlなど使うしかないだろ。
0407名無しさん@お腹いっぱい。
2006/11/21(火) 00:39:35evalつかえばなんでもできるって…
0408名無しさん@お腹いっぱい。
2006/11/21(火) 00:42:06-.*)
echo fail
;;
*)
echo success
;;
esac
0409名無しさん@お腹いっぱい。
2006/11/21(火) 02:31:42元ファイルを加工して1レコードが2フィールドで
接続開始時刻:接続終了時刻
の形式のファイルをawkを使って抽出してあります。
時刻は数値化(Excelの日付表示を数値表示に変換したもの)
されているので直接比較可能です。
スクリプトで処理したい作業は
あるレコードの接続開始時刻から接続終了時刻の間に
A 全レコード中、接続開始時刻が何件含まれているか
B 全レコード中、接続終了時刻が何件含まれているか
を各レコードの情報とともに表示させることです。
接続開始時刻:接続終了時刻:A件数:B件数
みたいに。
実際には同時接続数がどれぐらいあるかチェックしたいので
おおざっぱに掴めればなあと。
awkでレコードを1行読むごとに、全行比較という形で
スクリプトを書きかけたのですが、そもそも全行と
比較できず終わってしまっているようです。
{x=0;y=$1;z=$2;if ($1<=y && z<=$2) x=x+1;print x}
readlineが必要そうであれこれ試しているのですが、
こちらは全く使ったことがないので苦戦しています。
どなたかお知恵拝借させてください。
0410名無しさん@お腹いっぱい。
2006/11/21(火) 06:04:41まず
> A 全レコード中、接続開始時刻が何件含まれているか
> B 全レコード中、接続終了時刻が何件含まれているか
を実現する関数かスクリプトを作って
レコードを1行読むごとにそれを実行する、という方法はどう?
awk で関数なんて作ったことないから外しているかも。
0411名無しさん@お腹いっぱい。
2006/11/21(火) 09:49:42時刻 接続開始or終了
という形式のレコードを時刻でソートしてから頭からなめて
開始が来たら同時接続数++,
終了が来たら同時接続数--
としたほうが簡単じゃないか。
0412名無しさん@お腹いっぱい。
2006/11/21(火) 13:12:300413名無しさん@お腹いっぱい。
2006/11/21(火) 22:33:38どうすればいいんでしょうか?
0414名無しさん@お腹いっぱい。
2006/11/21(火) 22:49:550415名無しさん@お腹いっぱい。
2006/11/21(火) 22:52:060416名無しさん@お腹いっぱい。
2006/11/21(火) 22:57:010417名無しさん@お腹いっぱい。
2006/11/21(火) 22:59:240418名無しさん@お腹いっぱい。
2006/11/21(火) 23:05:44ファイル名に -> が入っている場合はアウトかと思っていましたが
やってみたらOKでした。ありがとうございます。
0419名無しさん@お腹いっぱい。
2006/11/23(木) 00:32:530420名無しさん@お腹いっぱい。
2006/11/23(木) 00:48:18全ての環境で共通に動かせるようにする道は死屍累々ですから。
0421名無しさん@お腹いっぱい。
2006/11/23(木) 02:53:37笑止。
真にマルチプラットフォームな言語なぞ無い。
0422名無しさん@お腹いっぱい。
2006/11/23(木) 09:16:15動かなかったら直せばいいだけ。
0423名無しさん@お腹いっぱい。
2006/11/23(木) 11:42:56所詮テキストファイルだし。
0424名無しさん@お腹いっぱい。
2006/11/23(木) 13:32:35異なる環境で動かすことを考えて作成されたシェルスクリプトに限定すれば真。
0425名無しさん@お腹いっぱい。
2006/11/23(木) 13:58:380426名無しさん@お腹いっぱい。
2006/11/23(木) 14:04:16いまでもアセンブリ書くよりはるかにポータブルだが…
0427名無しさん@お腹いっぱい。
2006/11/23(木) 14:07:320428名無しさん@お腹いっぱい。
2006/11/23(木) 14:15:22Cコンパイラ自身がポータブル。
0429名無しさん@お腹いっぱい。
2006/11/23(木) 14:16:43C言語のソースはポータブルだが、バイナリはポータブルじゃない。
だから、実行形式そのままをポータブルにしたい場合は
Cを使わずにシェルスクリプトで書くというのが常識。
0430名無しさん@お腹いっぱい。
2006/11/23(木) 14:21:50そういう時は C で極力ポータブルに書く。
0431名無しさん@お腹いっぱい。
2006/11/23(木) 14:22:06シェルスクリプトにヒアドキュメントでCのソース埋め込めばポータブル。
0432名無しさん@お腹いっぱい。
2006/11/23(木) 14:24:090433名無しさん@お腹いっぱい。
2006/11/23(木) 14:24:46「バイナリが」と言ってるだろ。
どこの世界に、バイナリレベルでポータブルなCがあるんだよ???
0434名無しさん@お腹いっぱい。
2006/11/23(木) 14:27:19シェルスクリプトで書くのはシェルスクリプトで良いやと判断した時だけ。
0435名無しさん@お腹いっぱい。
2006/11/23(木) 14:37:160436名無しさん@お腹いっぱい。
2006/11/23(木) 14:47:110437名無しさん@お腹いっぱい。
2006/11/23(木) 14:50:41という意味ではポータブルではない。
同様のことがperlとかにも言える。
シェルがインストールされていない環境はあり得ないので、
そういう意味でシェルスクリプトが最もポータブル。
0438名無しさん@お腹いっぱい。
2006/11/23(木) 15:01:39bash に link されてる奴は論外として…
0439名無しさん@お腹いっぱい。
2006/11/23(木) 15:39:46シェルだけで完結することはほとんどない。
さまざまな外部コマンドを使うことによって機能を実現できる。
つまり外部コマンドの仕様や配置などによって修正を余儀なくされるから、
ポータビリティはかなり低い。
また、それとは別にシェルそのものの実装違いもあるし。
0440名無しさん@お腹いっぱい。
2006/11/23(木) 15:51:36それは人のレベルによる問題。
普段からポータビリティを気にしてシェルスクリプトを書いていれば、
たとえ外部コマンドを使うにしても、どのOSでも使えるコマンドとオプションの
範囲だけで書く癖が付いているから、ポータビリティの高いスクリプトを
書くことは簡単にできる。逆に、別のOSで動かす予定がなかったのに、
たまたま別のOSでも動かす機会があった時に、そのまま動いてしまうことがほとんど。
一方、Java/perlとかだと、インストールされていなければそこで終り。
0441名無しさん@お腹いっぱい。
2006/11/23(木) 16:02:23シェルスクリプトがポータブルな範囲でのみ仕事を受け付けます。
0442名無しさん@お腹いっぱい。
2006/11/23(木) 17:01:590443名無しさん@お腹いっぱい。
2006/11/23(木) 17:41:210444名無しさん@お腹いっぱい。
2006/11/23(木) 18:41:14ガンガレ
0445名無しさん@お腹いっぱい。
2006/11/23(木) 19:48:590446名無しさん@お腹いっぱい。
2006/11/23(木) 19:51:570447名無しさん@お腹いっぱい。
2006/11/23(木) 20:02:230448名無しさん@お腹いっぱい。
2006/11/23(木) 20:09:25シリアライズして渡すのかな。ネットワーク越しにも渡せるの?
0449名無しさん@お腹いっぱい。
2006/11/23(木) 20:24:33詳しくはしらんけど
http://www.atmarkit.co.jp/fdotnet/special/powershell02/powershell02_01.html
cmd.exeより100倍ほどつかいやすそうだ。
0450名無しさん@お腹いっぱい。
2006/11/23(木) 20:26:48■ このスレッドは過去ログ倉庫に格納されています