トップページunix
987コメント278KB

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

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2012/11/15(木) 18:57:33.11
シェルスクリプトの総合スレです。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashまたはdashなので特に注意。
 FreeBSDユーザは/bin/shの正体がashなので注意。
 v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。
  http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/sh/
  http://heirloom.sourceforge.net/sh.html
・csh/tcshのシェルスクリプトは推奨されません。
 (理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
 manや参考リンクを見ましょう。
 aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルで使えるワイルドカード等は正規表現ではありません。
 正規表現の話題はスレ違い(正規表現スレへ)
・シェルスクリプトのことをシェルってゆーな
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 awkまたはperlの方が適した処理にはそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
□回答者への注意事項:
・シェルスクリプトでの処理方法を質問しているのに、よくわからずに
 「そういうのはperl使いましょう」と回答するのはやめましょう。
 安易にperlに逃げずにシェルスクリプトで処理するのが頭のいいやり方。
前スレ
シェルスクリプト総合 その20
http://toro.2ch.net/test/read.cgi/unix/1339083351/
0595名無しさん@お腹いっぱい。2013/05/17(金) 07:17:32.96
>>594
read: 1: Illegal option -n
0596名無しさん@お腹いっぱい。2013/05/17(金) 07:19:27.17
>>593
key=`dd bs=1 count=1 2>/dev/null`
0597名無しさん@お腹いっぱい。2013/05/17(金) 07:26:23.44
>>596
stty cbreak 忘れてるぞ
事後に元に戻すのも忘れずにな。
0598名無しさん@お腹いっぱい。2013/05/17(金) 19:43:56.07
inkey$ を使えばいいニダ
0599名無しさん@お腹いっぱい。2013/05/17(金) 20:19:56.75
シェルじゃなくperlとかpythonとかのほうが楽?
0600名無しさん@お腹いっぱい。2013/05/17(金) 20:28:35.33
人によるんじゃない?
0601名無しさん@お腹いっぱい。2013/05/18(土) 01:17:39.94
perl も python も
インストールされていない
ということもあるw
0602名無しさん@お腹いっぱい。2013/05/18(土) 22:44:45.05
入力された拡張子を持つファイル一覧を出すスクリプトを作ろうと思ってるけどうまくいかない…
ボスケテ

#!/bin/sh
cd trash
extension=$@

ls | grep $extension

cd

extension経由させてんのはgrepだと正規表現とかが関係してうまくいかないんじゃないかと思ったから
助けてくれ…さっぱりわからないし調べても出てこない
0603名無しさん@お腹いっぱい。2013/05/18(土) 23:26:55.16
>>602
何がうまく行ってないのか説明してくれないと分からん。
0604名無しさん@お腹いっぱい。2013/05/18(土) 23:38:08.84
これを例えばtxtもつ奴だけ並べようとして実行すると(ファイル名challe5)
./challe5.sh* txt
grep: txt をオープンできません。
と出てそこで終了してしまう
どうすればいいんだ
0605名無しさん@お腹いっぱい。2013/05/19(日) 00:45:21.09
>>604
./challe5.sh* txt
の * は何のため?
ひょっとして、次のように * の前後に空白が這いよってない。
./challe5.sh * txt
0606名無しさん@お腹いっぱい。2013/05/19(日) 01:11:17.99
>>605
できた!
./challe5.sh txt で正しく動いた
ありがとう
0607名無しさん@お腹いっぱい。2013/05/19(日) 09:22:36.36
もしかして、 ls が ls -F に alias されていて、
実行可能ファイル名に末尾に * がついてたのを
勘違いしたんだろうか。
0608名無しさん@お腹いっぱい。2013/05/19(日) 12:09:10.88
解決まで読んでも何がしたいのか、さっぱりわからんw

ls ./trash/*.txt
で済んでしまいそうな。
あと多分cd -の方がいい。
0609名無しさん@お腹いっぱい。2013/05/20(月) 11:46:33.00
スクリプトに引数渡す練習かな。
最後に cd する理由はよくわからん。cd - に変える必要もないっしょ。
0610名無しさん@お腹いっぱい。2013/05/20(月) 14:29:43.96
元のデレクトリに戻したいだけだろ
そもそもcd trashが不要だろというのはおいといて
0611名無しさん@お腹いっぱい。2013/05/20(月) 14:53:12.21
元のディレクトリに戻ったところで
スクリプトの実行終わったら関係ないよね。
0612名無しさん@お腹いっぱい。2013/05/20(月) 15:00:49.43
わからねえならいいや
俺には関係ねえし
0613名無しさん@お腹いっぱい。2013/05/20(月) 15:38:14.12
>>612
オレもマジで分からんが。
スクリプト内の最終行で、元のディレクトリに戻らなければならない事例を挙げてくれよ
0614名無しさん@お腹いっぱい。2013/05/20(月) 16:15:55.91
気分がいいんじゃないか?
0615名無しさん@お腹いっぱい。2013/05/20(月) 17:03:05.27
何かやってて何か調べてwdに戻りたいつーだけだろ
わからねえならいいつってんのも読めないのかよ知障
0616名無しさん@お腹いっぱい。2013/05/20(月) 19:21:55.30
>>615
君がよくても、我々がよくない。
開き直って逆ギレしないで、
我々の知的好奇心を満たすために協力したまえ
0617名無しさん@お腹いっぱい。2013/05/20(月) 19:41:21.85
>>613
次に実行するスクリプトのためだろ

そういうコード書くな、で済むならいいけど
現実そういうわけにもいかないし
それなら毎度立つ鳥跡を濁さない方がいい
0618名無しさん@お腹いっぱい。2013/05/20(月) 20:24:44.35
>>617
最後に元のディレクトリに戻っても戻らなくても
次に実行するスクリプトには関係なくね?
0619名無しさん@お腹いっぱい。2013/05/20(月) 20:30:45.71
source や . で呼ばれるときに備えて元のディレクトリに戻っておくのはあるかもね。
>>602 がそこまで考えてるかどうか分からんけど。
0620名無しさん@お腹いっぱい。2013/05/20(月) 20:46:26.14
そんな呼び方するかねぇ。
0621名無しさん@お腹いっぱい。2013/05/20(月) 21:25:45.61
>>620
されたときのことを考慮するんだよ
0622名無しさん@お腹いっぱい。2013/05/20(月) 21:49:57.22
無引数cdした方がいいかどうかわからんだろ。
sourceされた時のことを考えて、(cd ...; xxx)ならまだわかるが。
06236022013/05/20(月) 21:51:17.99
最後のcdは元の場所に戻っておきたいなーと思って入れといた
ls ./trash/*txt は単に思いつかなかったw
>>607はたぶん大当たり
ガッコの課題でそういうシェルプログラム組めって言われたからつい大仰なのを作ってしまった
物議を醸してすまなかったぜ
0624名無しさん@お腹いっぱい。2013/05/20(月) 21:52:31.15
ちなみにcdだけでホームディレクトリ(でいいのか?)に戻るようになってる
(普通もそうなってるかはわからんので補足)
0625名無しさん@お腹いっぱい。2013/05/20(月) 21:54:30.64
学校の課題なのは薄々気付いてたけど
そんなに大仰でもないような。
0626名無しさん@お腹いっぱい。2013/05/20(月) 21:56:34.48
俺にとっては大仰なんだよ!
0627名無しさん@お腹いっぱい。2013/05/20(月) 22:24:58.07
>>623
なんで戻っておきたいの?
0628名無しさん@お腹いっぱい。2013/05/20(月) 22:46:30.24
>>623
> 最後のcdは元の場所に戻っておきたい
それなら、>>608の指摘通り「cd -」とすべきだな。
cdだと、元の場所ではなくて$HOMEに移動してしまう。
元の場所が$HOMEなら、同じだけど。

>>618
おぉ、sourceや . で呼び出すときの挙動をよく考えたことがなかったので、
ちょっと実験してみよう。
0629名無しさん@お腹いっぱい。2013/05/20(月) 22:46:37.20
はっきりいって特に戻っておきたい、と思った明確な理由はない
ただなんとなくつけただけだ
その上で、強いて理由を挙げるのであれば、ホームディレクトリでこのプログラムを起動した後
一回trashに言ったままになっちゃうのが面倒と思ったから

察して試してみたが別にcd無くても勝手に元に戻るみたいね…
0630名無しさん@お腹いっぱい。2013/05/20(月) 22:48:00.34
もちろんもとの場所も$HOMEです(おそらく)
0631>>6022013/05/20(月) 22:49:16.68
>>629-630は俺です
お目汚し失礼しました
0632名無しさん@お腹いっぱい。2013/05/20(月) 23:01:09.18
>>629
> 察して試してみたが別にcd無くても勝手に元に戻るみたいね…
「戻る」っていうか、
そのプロセスのカレントディレクトリは変わってないんだよ。
スクリプトとして呼ばれた子プロセスのカレントディレクトリが変わってるだけで。
0633名無しさん@お腹いっぱい。2013/05/20(月) 23:01:58.11
>>629
仮に「戻る」としても、
ホームディレクトリ以外にいるときに実行することは考えないのか?
0634名無しさん@お腹いっぱい。2013/05/20(月) 23:07:47.22
>>632 なるほど
>>633 それは確かに考えるべきだったな
書いたときは全然考えなかったわ(授業でやってる事は今のところ全部ホームディレクトリでやってるから)
まあ、初心者故に考えなかった、ってことだな
0635>>6022013/05/20(月) 23:08:44.03
>>634も俺
0636名無しさん@お腹いっぱい。2013/05/21(火) 00:30:10.63
ここは、書いたシェルスクリプトの投稿とかありか?
評価してほしいんだが
0637名無しさん@お腹いっぱい。2013/05/21(火) 00:50:08.35
やっぱいいや
0638名無しさん@お腹いっぱい。2013/05/21(火) 01:02:43.56
ありだよ。
0639名無しさん@お腹いっぱい。2013/05/21(火) 01:53:42.08
#!/bin/sh
while true
do
echo 'SEX shitai'
done
0640名無しさん@お腹いっぱい。2013/05/21(火) 02:07:26.42
echo oremo shitai
0641名無しさん@お腹いっぱい。2013/05/21(火) 07:29:23.70
シェルの手動起動の課題をやってます。
メモ帳でテキストファイルにEcho Helloとだけ書いて
サンバでH:ドライブに test.sh という名前を付けて保存、
TeraTermでtest命令を発行してもうまくシェルが動きません。
何かヒントください。
0642名無しさん@お腹いっぱい。2013/05/21(火) 07:44:12.55
その質問の仕方では答えられません
何かヒントを下さい
0643名無しさん@お腹いっぱい。2013/05/21(火) 09:37:22.82
>>642
w

>>641
sambaとかTeraTermとかいうからWindows環境だと思うが、
Windows以外の世界は、case sensitiveだということを覚えておこう
0644名無しさん@お腹いっぱい。2013/05/21(火) 09:40:26.49
実行後にカレントディレクトリが変更されるスクリプト
ってどうやって書けばいいの?
0645名無しさん@お腹いっぱい。2013/05/21(火) 09:48:23.40
>>644
ttp://okwave.jp/qa/q5125847.html
| 子プロセス側の操作によって親プロセス (シェル) のカレントディレクトリ
| が変わってしまうようなUNIXのシェルというのは寡聞にして知りません。
0646名無しさん@お腹いっぱい。2013/05/21(火) 09:58:55.94
>>645
シェルの問題じゃなくて、UNIXというOSの設計の問題。perlでもCでもできない。
sh hoge.sh ではなく、. hoge.sh のように実行するとか、
cd hoge と出力するhoge.plを eval `perl hoge.pl` として実行するとかなら可能だが。

DOSはそうはなってないので、バッチファイル実行後にカレントディレクトリを変えられる。
0647名無しさん@お腹いっぱい。2013/05/21(火) 11:49:32.84
>>641
643に加えて
(1)そのファイルに実行権(プログラムやシェルスクリプトであることを示すフラグ)が必要
Windowsは拡張子によって、実行ファイルかが判断されるがUnix系はフラグによる。
chmod コマンドを参照

(2)Unix系は拡張子による区別がないので、コマンドとして実行する際に .sh 部分も必要

(3)Windowsのコマンドプロンプトはカレントディレクトリもコマンドの検索パスに含まれるが
Unix系ではカレントディレクトリが含まれていないことが多いため、カレントディレクトリに
あるコマンドは ./test.sh のようにディレクトリから指定する必要がある場合が多い。
0648名無しさん@お腹いっぱい。2013/05/21(火) 13:08:26.79
>>641はコピペ改変のネタでしょ。
まともに回答してもムダ。
0649名無しさん@お腹いっぱい。2013/05/21(火) 15:11:12.17
>>647
> (2)Unix系は拡張子による区別がないので

そんなことはない。
拡張子が大きな意味を持つ文脈もある。
0650名無しさん@お腹いっぱい。2013/05/21(火) 15:38:27.36
>>649
そうでしたね。
Windowsではコマンドとして実行する際に、ファイル名の .com .exe .bat(他にもあったかな)部分は
入力する必要がないがUnix系では、それもコマンド名の一部として入力する必要がある。
0651名無しさん@お腹いっぱい。2013/05/21(火) 17:21:49.35
>>645
そのひとが寡聞なだけやね。
0652名無しさん@お腹いっぱい。2013/05/21(火) 17:33:35.09
>>651
ん?
そういうシェルがある、ってこと?
0653名無しさん@お腹いっぱい。2013/05/21(火) 17:44:25.49
最近のOSは setcwd() が存在したりする
0654名無しさん@お腹いっぱい。2013/05/21(火) 17:51:07.72
関係ない
0655名無しさん@お腹いっぱい。2013/05/21(火) 18:00:44.07
int setcwd(pid_t pid, char *path);
0656名無しさん@お腹いっぱい。2013/05/21(火) 18:39:56.25
そういうネタはいらん。
0657名無しさん@お腹いっぱい。2013/05/21(火) 19:45:27.52
fork2(FORK_SHARECWD);
0658名無しさん@お腹いっぱい。2013/05/21(火) 20:25:00.38
>>657
どうせなら念願のファイルポインタ独立もよろしく

fork2(SHARECWD|FORK_UNSHAREFD);
0659名無しさん@お腹いっぱい。2013/05/21(火) 20:49:24.56
>>644
#!/bin/sh
cd ./tmp
/bin/sh ; exit
0660名無しさん@お腹いっぱい。2013/05/21(火) 21:27:11.56
>>659
それはスクリプト「実行後」じゃなくて「実行中」の別シェルだねw
ハイやり直し
0661名無しさん@お腹いっぱい。2013/05/21(火) 22:08:40.79
>>660
俺にとっても正解ではないが、
質問者にとってはこれで充分かもしれず。
0662名無しさん@お腹いっぱい。2013/05/22(水) 01:05:07.75
不十分だろう。
0663名無しさん@お腹いっぱい。2013/05/22(水) 10:31:50.02
. ドットコマンドについて、誰か
0664名無しさん@お腹いっぱい。2013/05/22(水) 10:34:02.64
ドットコマンドの話じゃないよ。普通の実行スクリプトで親シェルをcdする方法の話。
0665名無しさん@お腹いっぱい。2013/05/22(水) 11:10:54.23
もし、親プロセスのカレントディレクトリを変更できる仕組みがあったら
子プロセスを起動するプログラムはガクブルだな。
0666名無しさん@お腹いっぱい。2013/05/22(水) 12:04:13.10
>>665
だから、fork2(FORK_SHARECWD) で作成されたプロセスのみ可能なので安心して。
0667名無しさん@お腹いっぱい。2013/05/22(水) 13:53:26.90
>>663
help .
0668名無しさん@お腹いっぱい。2013/05/25(土) 18:42:48.92!
自分がスクリプトを書く環境で grep に -x オプションがないことが判明したのですが、
grep -x -F -f patlist に相当する処理をしたい場合はどうしたらいいですかね?

とりあえず -F をやめて patlist の各行を ^ と $ で囲む前処理をする? と思ったら、patlist
に含まれうる "." 等をメタ文字として解釈されてはまずいのでした。
grep を入れ直す、perl 等別のスクリプト言語を使う (sed/awk は OK。「言語」かどうかは
ともかく)、キレる等以外でお願いできますでしょうか。
0669名無しさん@お腹いっぱい。2013/05/25(土) 19:33:33.74
>>668
> 自分がスクリプトを書く環境
もしかして Solaris とかだったりする?
0670名無しさん@お腹いっぱい。2013/05/25(土) 19:46:11.01
効率を考えないのであれば
$ comm -12 <(sort patlist) <(sort hoge.txt)
で行けそうな気がする
0671名無しさん@お腹いっぱい。2013/05/25(土) 19:59:14.50
Solarisは grep -x あるぞ。というか、SunOS4の時代からある。
-xないってどこのOSだ?
0672名無しさん@お腹いっぱい。2013/05/25(土) 20:01:59.13
エスパーすると busyboxの grepとか
0673名無しさん@お腹いっぱい。2013/05/25(土) 20:10:20.17
bosyboxの shは、>>670 の named pipeは使えないな
06746682013/05/25(土) 20:56:40.98!
>>669
SUSで-xは規定されてるみたいですし...

>>670
comm もないのです

>>672
正解w


前処理として sed で patlist 内のメタ文字をエスケープすることもちょっと思ったのですが。
s/\([エスケープしたメタ文字リスト]\)/\\\1/g みたいな。ところでメタ文字のリストって?
06756682013/05/25(土) 22:01:26.16!
>>674
おっとっと、文字クラスの中ではエスケープは不要か。

実験してみると [ と ] を指定したいときに [[]]と書くと動かないけど[][]と書くと動くような。
ふむー
0676名無しさん@お腹いっぱい。2013/05/26(日) 05:51:54.34
>>674
-xが使えなくても -wで十分だったりするケースが多いんだけど。
あと、ウチのbusyboxではcommは使えるぞ。<(コマンド)の文法は使えないけど。
06776682013/05/26(日) 09:26:18.70!
>>676
それは元のデータが一行に一個しか単語を含まないとかそういう感じですか?
自分の場合そうではないので...

% echo foo bar | grep -x foo
% echo foo bar | grep -w foo
foo bar
0678名無しさん@お腹いっぱい。2013/05/26(日) 17:26:43.01
メタ文字をエスケープしたパターンを^$でくくればいい。
0679名無しさん@お腹いっぱい。2013/05/26(日) 17:38:36.63
>>678
だから、メタ文字をエスケープすることが難しいって話だろ。
0680名無しさん@お腹いっぱい。2013/05/26(日) 17:48:23.97
sedやawkでやればいい
06816682013/05/27(月) 18:41:29.35!
個々のメタ文字をエスケープしようかな、というのは前の方にに書いたんですが。
ただ正規表現もいろいろあったりするし、その方法はなんか嫌な感じがw
busybox の grep が -x をサポートしない時点で正規表現の方にも一抹の不安がw

まあ仕方ない、grep が扱いそうな正規表現ということで、
sed 's/[][^.$*\]/\\&/g' でいいですかねえ。
でそこに s/^.*$/^&$/ を付けて処理すれば文全体にマッチするパターンになると。
0682名無しさん@お腹いっぱい。2013/05/27(月) 19:11:46.88
awk 'BEGIN{while(getline<"patlist")a[$0]=1}{if($0 in a)print}'
0683名無しさん@お腹いっぱい。2013/05/27(月) 21:50:54.04
結局、環境はbusyboxなの?
0684名無しさん@お腹いっぱい。2013/05/27(月) 23:06:54.89
>>683 節穴
06856682013/05/28(火) 01:03:20.06!
>>682
おおー素晴らしい。そっか連想配列がありましたよね...
元の grep -v の話に合わせるなら !($0 in a) とすると。
0686名無しさん@お腹いっぱい。2013/06/20(木) 10:38:54.93
圧縮されたファイルをハードディスクに展開せずに
読み込ませるシェルスクリプトを書けないでしょうか

今までmkfifoでパイプを利用して
mkfifo input
xz -dc input.xz > input &
fortran.out < input
として必要なinput.xzの個数分コマンドラインで実行をしていました

inputファイルが増えてきたのでシェルスクリプトを使おうとしたのですが
バックグラウンドでパイプへ展開しながら
実行ファイルに読み込ませる方法が分かりません
0687名無しさん@お腹いっぱい。2013/06/20(木) 11:26:02.34
>>686
結局 fortran.out も stdinから読んでるんだから、

xz -dc input.xz | fortran.out &amp;

でいいんじゃないの? mkfifoする必要なし。

for で回すなら、

for file in .....
do
xz -dc "$file".xz | fortran.out &amp;
done
0688名無しさん@お腹いっぱい。2013/06/20(木) 11:30:04.73
それで行けるならこんな質問しないだろうな。
たぶん質問のしかたが悪い。
0689名無しさん@お腹いっぱい。2013/06/20(木) 11:33:07.90
mkfifo使うにしても、質問で input の文字列のところを $hoge 変数にして
ループ回すだけだし、それで行けるならこんな質問しないのか?
0690名無しさん@お腹いっぱい。2013/06/20(木) 11:39:30.71
お前らよくこんな質問にレスを付けようと思うな。
文体は丁寧だが、目的語などを省略して、相手に理解させる配慮が一切ない、
自分しか理解できない文章で質問する奴はスルーでいいだろ。
0691名無しさん@お腹いっぱい。2013/06/20(木) 11:41:17.87
いいじゃん答えても。
スルーでいいと思う人はスルーしてればいいじゃない。
0692名無しさん@お腹いっぱい。2013/06/20(木) 11:50:41.37
>>686
普通に「&」でバックグランドジョブにしてもダメなのかな。
0693名無しさん@お腹いっぱい。2013/06/20(木) 12:35:01.18
>>690
お前少し黙ってろよ
06946862013/06/20(木) 12:49:13.79
>>688
>>690
すいませんでした。
考え直します。
■ このスレッドは過去ログ倉庫に格納されています