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

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

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

前スレ
シェルスクリプト総合 その12
http://pc11.2ch.net/test/read.cgi/unix/1218277263/
0488名無しさん@お腹いっぱい。2008/12/08(月) 21:51:54
>>487
だからちゃんと見てやれよw
04894872008/12/08(月) 22:49:22
>>488
あ、ごめん、俺のは横レスだから>>485あたりの人とは別人

>>455見る限りでは、GNUではないsedだから置換文字列に\nが
使えなくてああいう書き方をしてて、それがいやだってんでしょ?
そう読めたけど
0490名無しさん@お腹いっぱい。2008/12/08(月) 22:53:55
>>484>>485>>486
俺には^Jをどう表示するかというエディタの問題に思えるが…
>>456>>459>>466>>487
禿同
0491名無しさん@お腹いっぱい。2008/12/09(火) 04:04:02
Linux板では回答が貰えないようなのでこちらに来てみました。

分かる方が居たらお願いします。
http://pc11.2ch.net/test/read.cgi/linux/1210999497/611
0492名無しさん@お腹いっぱい。2008/12/09(火) 10:23:37
ssh-agent 使えって示唆が出ているが?
0493名無しさん@お腹いっぱい。2008/12/09(火) 10:29:17
2スレ並列でやる必要もあるまい。
0494名無しさん@お腹いっぱい。2008/12/10(水) 22:03:11
AIXに導入するシェルを作ってるんですけど・・・。
if [ 変数 != 文字列A ] | [ 変数 != 文字列B ];then
ERROR処理
fi

ネスト無しでやる場合これって有りかな?
数値じゃないから-oは使えないんでこれしかやりようがなかったんすけど
有識者の方頼みます
0495名無しさん@お腹いっぱい。2008/12/10(水) 22:08:05
>>494
| じゃなくて || な。

if [ 変数 != 文字列A ] || [ 変数 != 文字列B ]; then


あと、数式じゃなくても -o 使えるよ。

if [ 変数 != 文字列A -o 変数 != 文字列B ]; then


-o が使えないのは [[ ]] の場合。その場合は、

if [[ 変数 != 文字列A || 変数 != 文字列B ]]; then
0496名無しさん@お腹いっぱい。2008/12/10(水) 22:12:30
しかし、「変数」が同じ変数なら、
意味的には、やりたいことは -o (||) じゃなくて、-a (&&) のような気がする。
0497名無しさん@お腹いっぱい。2008/12/10(水) 22:14:20
>>494
この場合、if [ ] よりも case を使った方が簡単に書けるよ。
0498名無しさん@お腹いっぱい。2008/12/10(水) 22:17:11
>>495
実は|でいけたんっすよ
テストケース作って試したんですけど、一応正常系も異常系も通りました。。。
-oについては明日また試してみます
ありがとうございます
0499名無しさん@お腹いっぱい。2008/12/10(水) 22:20:22
>>497
ミドルのステータスチェックを増やしたんすよ
元が共通シェルだから余り大幅な変更は出来ないんです
caseの方が良いのはその通りなんですが・・
0500名無しさん@お腹いっぱい。2008/12/10(水) 22:21:10
>>498
行けたように勘違いしただけで正常に変数チェックされていない。
| は パイプ。パイプでは、A | B の場合、Bが真か偽かしかチェックされない。
(Aは無関係になる)

具体的には、
if [ 変数 != 文字列A ] | [ 変数 != 文字列B ];then
だと、
[ 変数 != 文字列B ] だけがチェックされて、
[ 変数 != 文字列A ] の結果は無視される。
それをたまたま「行けた」と勘違いしただけ。

全然行けてないので勘違いしないように。
0501名無しさん@お腹いっぱい。2008/12/10(水) 22:25:43
>>500
確かに文字列Bの追加したステータスチェックは通ったけど、文字列Aは怪しいですね。
了解しました
参考にさせていただきます。

>>495
>>496
>>497
>>500
有難うございました。
0502名無しさん@お腹いっぱい。2008/12/10(水) 23:16:01
「シェル」を作っているのですね?
0503名無しさん@お腹いっぱい。2008/12/11(木) 01:28:58
簡単なコンソールゲームを作りたいんですけど
下の1から3に画面を変えるときは
clearして全部表示しなおすしかないですかね?
表示しなおしたい部分だけ変えるってできないのかな?

1.
□■□
□□□
□□□

2.
□□□
□■□
□□□

3.
□□□
□□□
□■□
0504名無しさん@お腹いっぱい。2008/12/11(木) 01:57:32
ANSI系端末決め打ちなら、
エスケープシーケンス出力してカーソル動かせばいい。

zshならcursesモジュールがあるから端末独立なスクリプトも書けるだろうけど。
0505名無しさん@お腹いっぱい。2008/12/11(木) 08:43:50
>>503
tput使え。
例えばtput cuu1がカーソルを一行上げる。
tput homeで左上へ移動。
0506名無しさん@お腹いっぱい。2008/12/11(木) 21:06:49
>>503
シェルでは無理。
強いてやるなら、echo;echo;echo;echo;.... で画面を全部流してから、
新しい画面の文字を全部 echoし直すしかないかな。
0507名無しさん@お腹いっぱい。2008/12/11(木) 21:19:52
tput cup ROW COL
0508名無しさん@お腹いっぱい。2008/12/11(木) 21:25:15
http://www.youtube.com/watch?v=HaKhw2nUgTk
0509名無しさん@お腹いっぱい。2008/12/11(木) 21:27:42
カーソル移動がcupかどうか(というか、terminfoかtermcapか)は、OSによる。
FreeBSDならcm。
0510名無しさん@お腹いっぱい。2008/12/11(木) 23:25:31
的外れかも知れないけどエスケープシーケンス使ってグリグリ書くのは駄目なん?
0511名無しさん@お腹いっぱい。2008/12/11(木) 23:37:36
>>509
tputって OS間の互換性ないんだな。
0512名無しさん@お腹いっぱい。2008/12/15(月) 22:27:41
「HP-UXの質問はココだ No4」から移動してきました。
HP-UX11iv2orv3でファイルをある一定の法則に従う複数のディレクトリにコピーするコマンドについて
お知恵をお貸しください。

たとえば、下記のようなディレクトリに同一のファイルを配置したいのですが
論理ホスト名が異なるサーバでも同じコマンドで実行できるようできませんか。

/etc/opt/論理ホスト名1/sh/
/etc/opt/論理ホスト名2/sh/
/etc/opt/論理ホスト名3/sh/

RHELの場合、下記コマンドで実行できたのですが
HP-UXでは、{}を単独で使わないと、検索したパスに置き換えてくれないようです。
(下記記述だと{}を{}そのもので認識されてしまいました。)

find /etc/opt/ -type d -path */sh -exec cp 配布元ファイル {}/配布先ファイル \;
配布元ファイル名と配布先ファイル名は、異なる場合でも対応できるようにしたいです。

よろしくお願いします。
0513名無しさん@お腹いっぱい。2008/12/15(月) 22:31:32
>>512

for dir in /etc/opt/*/sh
do
cp 配布元ファイル $dir/配布先ファイル
done
05145122008/12/15(月) 23:07:52
>>513

レスありがとうございます!!
forは思いつきませんでした
0515名無しさん@お腹いっぱい。2008/12/21(日) 16:32:11
HP-UXではtreeコマンドがないので、以下のシェルで代用しているのですが
http://ash.jp/ash/src/csh/tree.txt

どうせならファイルの詳細情報も表示させたいと思っています。

今のままだと以下の表示なのですが、
+---bin/
+---boot/
|  +---efi/
|  |  +---EFI/

以下のように表示させたい。どうすればよいですか?
+---bin/           drwxr-xr-x 2 root root 4096 2008-12-21 16:11
+---boot/           drwxr-xr-x 5 root root 1024 2008-10-26 05:21
|  +---efi/         drwxr-xr-x 13 root root 4200 2008-12-21 16:03
|  |  +---EFI/       drwxr-xr-x 115 root root 12288 2008-12-21 16:11
0516名無しさん@お腹いっぱい。2008/12/21(日) 17:03:18
あんたは、たとえばawkスクリプトであっても
「以下のawkで代用しているのですが」みたいに書くのか?
0517名無しさん@お腹いっぱい。2008/12/21(日) 17:20:45
>>516
すみませんが、質問だけに答えてください。
0518名無しさん@お腹いっぱい。2008/12/21(日) 17:31:31
 .|  ./川\  |
  \/┏┷┓\/
     。┃お┃。
  ゙ # ゚┃断┃; 。
   ; 。 ・┃り.┃・ #
  。 ;゙ #┃し.┃# 。
  ゙・# : ┃ま┃。 ; 。
 .;:# ゙。゚┃す┃゚ 。 #
 ; 。;; ゙.:。┗┯┛。 # : #
.   ハ,,ハ  |
.  ( ゚ω゚ ) |
  :/  つΦ
0519名無しさん@お腹いっぱい。2008/12/21(日) 21:35:57
>>517
シェルで代用とはどういう事ですか?
0520名無しさん@お腹いっぱい。2008/12/21(日) 22:53:31
>>519
シェルで代用もご存知ない方には聞いていません。

ハイ、次のもっと優秀な回答者

0521名無しさん@お腹いっぱい。2008/12/21(日) 23:17:51
この慇懃無礼な書き込み以前もどこかで見たような?
Emacsスレか?
0522名無しさん@お腹いっぱい。2008/12/22(月) 01:26:40
find . -ls で我慢しなさい
0523名無しさん@お腹いっぱい。2008/12/22(月) 10:13:41
cshだよ!
0524名無しさん@お腹いっぱい。2008/12/22(月) 10:23:11
シェルってゆうな。クズ。
0525名無しさん@お腹いっぱい。2008/12/22(月) 15:25:41
FreeBSDのサーバーには freeコマンドがなく、
不便なのでシェルを作ろうと思うのですが、
具体的にはどう作ればいいですか?
0526名無しさん@お腹いっぱい。2008/12/22(月) 15:32:50
そういう釣りはやめれ。
0527名無しさん@お腹いっぱい。2008/12/24(水) 22:22:39
カレントのディレクトリのを見て各ディレクトリの階層がいくつあるのかを出力したのですが
うまいこといきますか

ちなみにディレクトリ名は日本語だったりスペースありだったり()あったりです。
0528名無しさん@お腹いっぱい。2008/12/24(水) 22:38:09
日本語があれでよくわからんが、
改行がないなら、findして、/の個数を数えて、最大値でも出せばどうかね?
0529名無しさん@お腹いっぱい。2008/12/24(水) 22:57:34
まずカレントにあるディレクトリのリストが取れないです。
find ./ -type d だと再帰的になってしまうので
ls -l | egrep '^d' | awk ' { print $8 } '
みたいにしたら、スペース込みのディレクトリ名の場合8カラム目以降消えてしまうし
0530名無しさん@お腹いっぱい。2008/12/24(水) 23:00:07
-depth のない find か?
0531名無しさん@お腹いっぱい。2008/12/24(水) 23:18:57
-depthというの初めて知りました・・
ちっと出直してきます
0532名無しさん@お腹いっぱい。2008/12/25(木) 06:51:30
おいおい、-depthがあるfindでも無理だろ。
(-depthはあっても-maxdepthがないfindは存在する)
0533名無しさん@お腹いっぱい。2008/12/25(木) 07:54:35
まずはカレントディレクトリ直下のサブディレクトリを列挙したいんだろ。
-depth 1 -type d で要求は満たす。
-maxdepth 1 を指定すれば効率はよくなるだろうけど、
ないと無理という根拠が不明。
0534名無しさん@お腹いっぱい。2008/12/25(木) 07:56:58
>>533
おいおい、何か勘違いしてないか?
-depth に引数は付かない。
全く要求を満たさない。
試してから書けよな。
0535名無しさん@お腹いっぱい。2008/12/25(木) 08:02:07
たぶん、>>533 は、FreeBSD方言の-depthのことを言ってるな。
一般のfindの-depthじゃ、>>534 の言う通り、無理なんだよ。(例:Solaris)
0536名無しさん@お腹いっぱい。2008/12/25(木) 08:13:34
GNU find にも -depth n がないのか。俺が悪かったわ。
0537名無しさん@お腹いっぱい。2008/12/25(木) 08:49:50
-maxdepth nはあるが。
0538名無しさん@お腹いっぱい。2008/12/25(木) 12:01:09
find -depth n ってBSD方言だったのか。。。知らなかった
0539名無しさん@お腹いっぱい。2008/12/25(木) 13:53:10
>>536
はいって何?
出来るの?
さっきから何度も。
はいって言葉の重みわかってる?
いま出来ますって断言したんだよ君。
その責任の重さわかってんの?
社会に出たらもっと自分の言葉に責任持てよ。
ん?
社会人の一言一言に掛かる責任の重さが分かってないだろ全然。
学生気分でやってんだったら帰ってもらうよ。
とにかく明日はもう来なくていいから。
0540名無しさん@お腹いっぱい。2008/12/25(木) 16:31:48
>>539荒らしは帰れ。以上。
0541名無しさん@お腹いっぱい。2008/12/25(木) 22:30:58
ワイルドカードを展開して test で調べるんじゃだめなの?
0542名無しさん@お腹いっぱい。2008/12/25(木) 22:31:23
シェルスクリプト(bash)を勉強するのにお勧めの本ありますか?
0543名無しさん@お腹いっぱい。2008/12/25(木) 22:34:56
>>541
.で始まったりすると面倒じゃね
0544名無しさん@お腹いっぱい。2008/12/25(木) 22:50:31
>>543
標準bourne shellにこだわらなければ、
.で始まるファイルをファイル展開に含める方法があるシェルが最近は多い。
0545名無しさん@お腹いっぱい。2008/12/25(木) 22:59:07
(不正確な記憶) .[^.]* * とか書けばいいんじゃなかったけ?
0546名無しさん@お腹いっぱい。2008/12/25(木) 23:06:48
>>545
..aaが含まれない。
.* *で.と..を省いた方がまだいい。
0547名無しさん@お腹いっぱい。2008/12/26(金) 06:44:52
ls -A -F | grep '/$' | sed s/\\///
0548名無しさん@お腹いっぱい。2008/12/26(金) 22:53:28
結局ディレクトリが空か見るのって
find hogedir -type f | wc -l
とかしか無いの?
かっこいいのないのかね
0549名無しさん@お腹いっぱい。2008/12/26(金) 23:10:57
ls -A hogedir | wc -l の方がましでは?
0550名無しさん@お腹いっぱい。2008/12/27(土) 03:40:29
>>548
hogedir 以下にディレクトリがあっても空とみなすの?
0551名無しさん@お腹いっぱい。2008/12/27(土) 04:20:31
文字列置換え処理で質問です!以下の3つのファイルがあるとします。

$ cat a.dat
111
AAA
BBB
CCC
222
$ cat b.dat
AAA
BBB
CCC
$ cat c.dat
DDD
EEE
FFF

で、以下のように実行(hogeコマンドはあくまでイメージです)すると、
-------------------------
$ hoge -t a.dat -s b.dat -d c.dat
111
DDD
EEE
FFF
222
-------------------------
上のようになるコマンドはありますでしょうか?
そのようなコマンドがない場合、みなさんだったらどのようにこの置換えを行いますか?
0552名無しさん@お腹いっぱい。2008/12/27(土) 09:37:21
-tのデータで、
-sにあるものを
対応する-dの行で置き換えるってこと?
$ cat b.dat
BBB
AAA
なら、
111
EEE
DDD
CCC
222
ってこと?
0553名無しさん@お腹いっぱい。2008/12/27(土) 10:20:01
特定の例だけひっぱりだすんじゃなくて、言葉でちゃんと説明しろ
0554名無しさん@お腹いっぱい。2008/12/27(土) 12:05:09
>>549
case `ls -A hogedir` in '') 空の場合の処理;; esac

の方が、wcがいらない分まし。
0555名無しさん@お腹いっぱい。2008/12/27(土) 14:40:01
>>552
違います。すいません説明がたりませんでした。

ある領域に一致するものを、別の領域に置き換えるという意味です。
>>552の場合は、一致しないので置き換えないようになります。

0556名無しさん@お腹いっぱい。2008/12/27(土) 14:41:29
説明になってねえよ
0557名無しさん@お腹いっぱい。2008/12/27(土) 16:36:16
エスパーすると、

b.datの内容(3行全部)に完全に一致する部分を、
c.datの内容で置き換えるってことか。
0558名無しさん@お腹いっぱい。2008/12/27(土) 16:45:17
リンク数が2、というのは空ディレクトリの判定方法として
妥当だろうか。
ディレクトリのハードリンクについては考えないことにする。
0559名無しさん@お腹いっぱい。2008/12/27(土) 16:45:55
ディレクトリであって、かつリンク数が2ってことね。
0560名無しさん@お腹いっぱい。2008/12/27(土) 16:50:31
リンク==2
  → ディレクトリを含まないディレクトリ (通常ファイルはたくさんあっていい)
0561名無しさん@お腹いっぱい。2008/12/27(土) 17:37:58
>>558
だから、全然妥当じゃないねw
0562名無しさん@お腹いっぱい。2008/12/27(土) 20:47:01
手元でやってみたら、
MacOS XのHFS+→ファイルを作ると . へのンク数+1
Linuxのext3→ファイルを作ってもリンク数は増えない
となった。
0563名無しさん@お腹いっぱい。2008/12/27(土) 20:57:40
>>557
そのとおりです!

0564名無しさん@お腹いっぱい。2008/12/27(土) 22:35:22
>>558
おおむね妥当というか、定番の方法。

ただし、ダメなことがあるので、そのショートカットは省略できるように
色々なツールがオプション持ってるけどね。
0565名無しさん@お腹いっぱい。2008/12/27(土) 22:45:04
>>564
なんでやねん。

それは、ディレクトリが「leaf」かどうかを判断する方法であって、
「空」かどうかの判断にはなっていない。
ディレクトリ中に普通のファイルが存在しても、リンクカウントは2のままなんだから。
0566名無しさん@お腹いっぱい。2008/12/28(日) 09:20:08
しまった、空かどうかの話か。すまん。
それだとrmdirしてみるくらいしか思いつかないなぁ。
0567名無しさん@お腹いっぱい。2008/12/28(日) 12:50:04
rmdirは親ディレクトリに対する書き込み権限が無いと判定できない。
0568名無しさん@お腹いっぱい。2008/12/28(日) 13:14:22
一瞬でも消えると健全性が失われる可能性がある。
0569名無しさん@お腹いっぱい。2008/12/28(日) 14:45:24
だから、>>554 に答え出てるってw
0570名無しさん@お腹いっぱい。2008/12/28(日) 17:03:01
>>563
awk駆使するしかないかなー。
何気にあってもいいような気がするんだけど、そんなコマンドないんだよねー。
0571名無しさん@お腹いっぱい。2009/01/05(月) 01:38:25
すいません質問させてください。

/home/hoge
ディレクトリにある全てのファイルの改行コードを全部LF変更して上書きするシェルスクリプトを書きたいのですが、どう書けばよいでしょうか??
nkf -w -Lu samble.txt > sample.text
のようにやればよいのは知っているのですが、全ファイル一気に処理したい場合どうすればよいか分かりません。
ご教示いただけると幸いです。
0572名無しさん@お腹いっぱい。2009/01/05(月) 01:39:17
LF変更

LFに変更
です。。
0573名無しさん@お腹いっぱい。2009/01/05(月) 02:19:31
>>571
> nkf -w -Lu samble.txt > sample.text
> のようにやればよいのは知っているのですが

あかんで!
perl -iでも使えば。Encode/jcodeで変換して。
シェルスクリプトなら、

for i in *.txt; do
nkf -w -Lu $i > $i.--$$--
# 必要ならば yes no | mv -i $i $i.org
mv $i.--$$-- $i
done

0574名無しさん@お腹いっぱい。2009/01/05(月) 07:44:10
>>571
以下で桶。

#!/bin/sh
cd /home/hoge
for file in *.txt
do
out_file=`basename "$file" .txt`.text
nkf -w -Lu "$file" > "$out_file"
done


>>573
> あかんで!

なんであかんの?w

.txtと.textを読み落したか?w
上書きはしないよw
0575名無しさん@お腹いっぱい。2009/01/05(月) 08:08:46
foo.textあったら無条件に上書きするなあ
0576名無しさん@お腹いっぱい。2009/01/05(月) 08:54:26
--overwriteも--in-placeも無いnkfって古すぎないか?
% nkf -w -Lu --in-place=.bak *.txt
じゃね
0577名無しさん@お腹いっぱい。2009/01/05(月) 09:53:01
>>575
それはへ理屈。

>>573 の回答を見れば、.txtを.txtに変換しようとしてるので、
質問を読み間違えてるのは明らか。
しかも、スペース入りファイル名があると正常動作しないし。
知ったか回答者の典型。
0578名無しさん@お腹いっぱい。2009/01/05(月) 12:43:33
元がCRLF かLFならば
tr -d "\r" < input.txt > output.txt
で改行コードが変換できる。
0579名無しさん@お腹いっぱい。2009/01/05(月) 18:58:46
「ヒアドキュメントで書けるものは、必ず echo + パイプで書ける」
という命題は真ですか?
0580名無しさん@お腹いっぱい。2009/01/05(月) 19:44:54
日本語でわかりやすく
0581名無しさん@お腹いっぱい。2009/01/05(月) 19:50:14
>>580 は答えなくていいよ。
ハイ、次の回答者。
0582名無しさん@お腹いっぱい。2009/01/05(月) 20:03:21
0583名無しさん@お腹いっぱい。2009/01/05(月) 20:39:02
じゃあ、ヒアドキュメントはなくても困りませんね
0584名無しさん@お腹いっぱい。2009/01/05(月) 21:00:14
ないとかったるいね。
0585名無しさん@お腹いっぱい。2009/01/05(月) 21:15:47
複数の記法がある事に不都合はない。
0586名無しさん@お腹いっぱい。2009/01/06(火) 12:55:50
チューリングコンプリートであればコンピュータは1種類でよい、という主張と
似たようなもんだな。
0587名無しさん@お腹いっぱい。2009/01/06(火) 13:48:06
Whitespaceさえあればあとはいらん。
■ このスレッドは過去ログ倉庫に格納されています