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

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

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2009/01/29(木) 06:54:48
シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。


□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashなので特に注意。
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でそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)

□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。

前スレ落ちたみたいなのでリンク省略。
0233名無しさん@お腹いっぱい。2009/02/21(土) 19:08:07
>>232
X 入れてなくても日本語入力できてるけど、、

あと、>>229 で、「shに書く」なら出来てるんだよね?
どうやって shに書いてるの?
それと同じ方法でコマンドラインに日本語入力するだけだが、、
02342322009/02/21(土) 19:24:51
>>233

>>229 がどうしてるのかは知らんが、
x の入っているマシンで書いて、scpだ。

これと同じ方法でコマンドライン入力するとなると、
ssh comannd args ってなことになるが、リモートでシェルの補完機能が
使えない状況ではその気になれない。
0235名無しさん@お腹いっぱい。2009/02/21(土) 19:35:06
>>234
どんくさいね。
02362292009/02/21(土) 19:49:28
普通にデスクトップ環境です。(xfce)
これもfirefoxでカキコしてるし
gnome-terminal,Terminal,xtermいずれも日本語は表示するので
shの実行結果では日本語表示されます。

anthyでの変換画面はでるけれど変換終了すると日本語部分は表示されません。(ぴっとかはねられる)
コピペでもセレクションコピーでも同様
ただしnano等起動すればターミナル内でも日本語変換できます。
ちょっとスレの趣旨と別枠だけれど世間とは違うのですか。
02372292009/02/21(土) 19:50:59
むろんガチでダイアログ出すこともできるしperlを使う手もあるけれど
grepにそれはないでしょうということで一応質問しているわけであります。
0238名無しさん@お腹いっぱい。2009/02/21(土) 19:58:16
>>236
ロケール設定とshellの設定とターミナルの設定の問題だが、
スレ違いなんで、くだ質スレで、
「コマンドラインで日本語入力したい」ときいてみてくれ。
0239名無しさん@お腹いっぱい。2009/02/21(土) 20:09:13
>>234
その、Xが入ってるというマシンで日本語入力できてるなら、
xtermとかktermとか開いて、その中からsshでログインして、
ログイン先のシェルのコマンドラインに、ローカルのXの
いつもの入力方法で日本語入力できるだろ。
0240名無しさん@お腹いっぱい。2009/02/21(土) 20:15:44
>>226
shってゆうな。クズ。
02412322009/02/21(土) 20:39:48
>>235

なら、どんくさくない方法を提示しろやカス。
0242名無しさん@お腹いっぱい。2009/02/21(土) 20:40:57
canuumという単語を思い出したが意味は忘れた
0243名無しさん@お腹いっぱい。2009/02/21(土) 20:48:37
>>236
> 変換終了すると日本語部分は表示されません。(ぴっとかはねられる)

というのは、ログイン先でLANG(またはLC_ALLとかLC_CTYPE)が
ちゃんと設定されてないのが原因。

EUC環境なら LANG=ja_JP.eucJPに、
UTF-8環境なら LANG=ja_JP.UTF-8に設定しろ。


あと、これとは別件だが、canuumやuumがある環境なら、
Xが全くなくてもcanuumを起動すれば直接日本語入力できる。
0244名無しさん@お腹いっぱい。2009/02/21(土) 21:29:42
>>243
環境変数LANGによらず、シェルが8ビットコードに対応してないと
はじかれる。Solarisだと/bin/tcshは8ビット入力できなかった。

>>236 は別のシェルを使ってみるといいと思う

ただ、>>229 の「日本語を探索する場合」って漢字コードが混在していると
非常にやっかいなんだんだよね。昔 jgrep だか ngrep だかが fj.sources に
流れたような記憶があるけど、ああゆう漢字コードを変換する grep が欲しいかも
0245名無しさん@お腹いっぱい。2009/02/21(土) 21:38:48
>>241
「なら」ってなんだよ。つながってねーぞ。クズ。
0246名無しさん@お腹いっぱい。2009/02/21(土) 22:03:10
テラターム使って日本語入力すればぁ?
どうせUNIXはサーバー専用なんだろ?
0247名無しさん@お腹いっぱい。2009/02/21(土) 22:04:20
>236だす
>>243 環境変数は全部(LANGもLC_ALLもLC_CTYPEも)ja_JP.UTF-8なり
アプリだと入力できるのでターミナルソフトの問題ではなく>>244
いうようにシェルの問題だと思ったのだけれど

ふと思いついてsudo xterm(sh)するとなぜかコピペはできて変換はできず
su(csh)だとコピペも入力もできた。
原因は解明できていないしファイラーからターミナル開いて探索ということはやりにくいけれど
オラ個人の設定の問題の様なのでこの件はもうきにしないでくれ
grepの基本がわかっただけでも充分に前進したよ。
0248名無しさん@お腹いっぱい。2009/02/21(土) 22:06:00
>>246 UNIXはゲームしたり文章書いたりブラウジングしたりするパソコン用OS
0249名無しさん@お腹いっぱい。2009/02/21(土) 22:09:04
UNIXはゲームサーバーになったり書いた文章保存するサンバサーバーだったり
ブラウジング用ウェブサーバーだったりするサーバー用OS
0250名無しさん@お腹いっぱい。2009/02/21(土) 22:52:42
ちなみにターミナルで日本語打ち込めない対策はさすがにsuとか使えないので
perlで<STDIN>使うという最低の方法に逃げたです。これだとクリック起動で文字入力待ちしてPerlで組めばいいのに``でgrep呼んでしまいました。
単純な探索の場合処理的にはファイルをたぐるループ分perlで直接書くより速いと思います。
0251名無しさん@お腹いっぱい。2009/02/21(土) 23:04:53
>>250
$ grep -f - -rl .

ってやれよ。すると、標準入力から読み込んだキーワードがgrepに使われる。
シェルのコマンド行じゃない標準入力なら日本語は通るはず。
日本語打った後は、改行直後に Ctrl-Dで終了。
0252名無しさん@お腹いっぱい。2009/02/22(日) 00:34:27
>>244
だからlgrepがあるつーの。
0253名無しさん@お腹いっぱい。2009/02/24(火) 23:14:27
シェルの中でexpectを使ってwinにtelnetしてbatを実行してるんですが、
当然文字コードが違う(EUCとSJIS)ので化けます。

LANGを途中変えても変わらないです。(ターミナルのせいだと思いますが)

化けないようにできますか?
0254名無しさん@お腹いっぱい。2009/02/24(火) 23:19:46
>>253
・標準出力にパイプで | nkf -Se をかます
・ktermをSJISモードで開く

好きな方選べ
0255名無しさん@お腹いっぱい。2009/02/24(火) 23:30:46
| iconv -f EUC-JP -t Shift_JIS
0256名無しさん@お腹いっぱい。2009/02/24(火) 23:42:35
シェルってゆうな。クズ。
0257名無しさん@お腹いっぱい。2009/02/25(水) 06:36:32
>>255
それ、-t と -f 逆だろ。
0258名無しさん@お腹いっぱい。2009/02/25(水) 10:09:23
>>251 ほとんどすれ違いネタになっていたのにありがとうございます
grep -f - -rl .
後の日本語入力→改行→ctrl+dで探索スタートできました。(xterm)
0259名無しさん@お腹いっぱい。2009/02/25(水) 15:12:52
ディレクトリ内にひとつしかファイルorディレクトリがない場合に
コマンドを実行しようと思い、

for dir in `find . -type d -maxdepth 1`
do
    test $(ls -1 $dir | wc -l) -eq 1 && command
done

このように書いてみたのですが、ディレクトリ名が空白で区切られて
しまいうまく動きません。
どのように対処したらいいでしょうか?
0260名無しさん@お腹いっぱい。2009/02/25(水) 15:17:13
find . -type d -maxdepth 1 | while read dir
do
test $(ls -1 "$dir" | wc -l) -eq 1 && command
done
0261名無しさん@お腹いっぱい。2009/02/25(水) 15:28:47
>>259

find . -maxdepth 1 -type d \
-exec sh -c 'for d;do [ $(ls "$d"| wc -l) -eq 1 ] && command; done' dummy {} +
0262名無しさん@お腹いっぱい。2009/02/25(水) 16:21:38
>>260
ありがとうございます。readを使うと良いんですね。
無事目的の動作をさせることができました。

>>261
ありがとうございます。
-execはあまり使ったことがないのですが、最後の
done' dummy {} +
の意味がいまいち理解できませんでした。
よろしければ教えていただけますか?
0263名無しさん@お腹いっぱい。2009/02/25(水) 16:26:36
readを使うと、\ を含むディレクトリ名が読めないとか、
(途中じゃなく)頭にスペースが付いてるディレクトリ名が読めないとか
問題が残るんだな。
その点も含めて解決するとなると、>>261 の解になる。
0264名無しさん@お腹いっぱい。2009/02/25(水) 17:34:24
>readを使うと、\ を含むディレクトリ名が読めないとか、
>(途中じゃなく)頭にスペースが付いてるディレクトリ名が読めないとか

IFS= read -r
0265名無しさん@お腹いっぱい。2009/02/25(水) 17:36:23
>>264
read -r は bash依存。

で、それやっても「改行入り」ディレクトリ名が正しく処理されない。
結局 >>261 一択。
0266名無しさん@お腹いっぱい。2009/02/25(水) 17:48:53
read -r は posix じゃね?
0267名無しさん@お腹いっぱい。2009/02/28(土) 18:54:04
基本的なことかも知れませんが、
キーボードを読んで分岐するバッチはどう書けば医院でしょうか?
0268名無しさん@お腹いっぱい。2009/02/28(土) 19:04:18
バッチならset /pですね。でも板違いなので出てってください。
0269名無しさん@お腹いっぱい。2009/03/01(日) 02:23:56
>>268
MSDOSのバッチスクリプトしか知らない人?
バッチって、バッチ処理等の普通名詞だろう
0270名無しさん@お腹いっぱい。2009/03/01(日) 03:26:52
パスワードがかかってないzipファイルにパスワードをかけていきたいんですが、
そもそもパスワードがかかってないか判定するすべはありますか?
0271名無しさん@お腹いっぱい。2009/03/01(日) 06:54:24
>>270
unzip -Zv *.zip | grep 'file security status'
0272名無しさん@お腹いっぱい。2009/03/01(日) 08:06:08
cronもatも使えない環境で、指定日時時刻にシェルを実行するバッチって書けますか?
0273名無しさん@お腹いっぱい。2009/03/01(日) 11:17:51
>>269
普通名詞のバッチ処理はユーザーからの入力待ちは行えない。必要な入力データは
あらかじめ用意しておく処理。対話処理とは対極的なもの。
ユーザーからの入力によって処理を変えたい「バッチ」というならMSDOSのバッチに他ならない。
0274名無しさん@お腹いっぱい。2009/03/01(日) 11:20:52
>>272
指定時刻までの時間を計算してsleepする。
0275名無しさん@お腹いっぱい。2009/03/01(日) 11:27:52
>>274
それはわかってますよ。その具体的なシェルを質問してるんですが。
0276名無しさん@お腹いっぱい。2009/03/01(日) 11:29:40
echo -n 'xx時xx分xx秒までの時間を入力してください '
read t
sleep $t
command
0277名無しさん@お腹いっぱい。2009/03/01(日) 11:32:04
すみませんが、詳しくご存知の方のみ御回答をお願いします
0278名無しさん@お腹いっぱい。2009/03/01(日) 12:34:37
>>277
お前、何様のつもり?
0279名無しさん@お腹いっぱい。2009/03/01(日) 12:42:54
こういうのがはやってるみたいよ
0280名無しさん@お腹いっぱい。2009/03/01(日) 13:14:31
ttp://pc11.2ch.net/test/read.cgi/db/1057136328/188

これってシェルスクリプトで出来るんですか?
0281名無しさん@お腹いっぱい。2009/03/01(日) 16:28:03
>>277 は多分質問者じゃない。
こういう荒らしを楽しんでる奴が最近いる。
0282名無しさん@お腹いっぱい。2009/03/01(日) 18:03:41
そらできるよ
0283名無しさん@お腹いっぱい。2009/03/01(日) 19:27:53
bashとawkって書いてあるじゃん
0284名無しさん@お腹いっぱい。2009/03/01(日) 20:10:39
bashはわかりますが、awkって何ですか? bashのプラグインみたいなものとは思いますが
0285名無しさん@お腹いっぱい。2009/03/01(日) 20:44:21
その認識でおk
0286名無しさん@お腹いっぱい。2009/03/01(日) 21:02:50
工エエェ(´д`)ェエエ工
0287名無しさん@お腹いっぱい。2009/03/01(日) 21:03:02
bashとawkでGUIができるの?
0288名無しさん@お腹いっぱい。2009/03/01(日) 23:21:15
久々に笑った。
まさかbashのプラグインと来るなんてねえ。
0289名無しさん@お腹いっぱい。2009/03/02(月) 09:25:51
>>287
GUI とhttp通信は別コマンドじゃないかな
awkを書いたのはCSVのparseに使ってるからだろうね
0290名無しさん@お腹いっぱい。2009/03/02(月) 15:07:18
すみませんが、まったくの素人の方のみ御回答をお願いします
0291名無しさん@お腹いっぱい。2009/03/03(火) 10:58:08
$ echo abcd def | read a
$ echo $a


echo の結果を read では変数にセットできない?
0292名無しさん@お腹いっぱい。2009/03/03(火) 11:05:13
できるよ。
ただ、| のうしろはサブシェルになるので、
セットしてすぐサブシェルが終了して忘れるだけ。

echo abcd def | { read a; echo $a; }

ksh だとサブシェルにならないので↑のようにしなくてもふつーに動く。
0293名無しさん@お腹いっぱい。2009/03/03(火) 11:43:30
なるほど、ありがと。
大人しくバッククォートで実行の結果使います。
0294名無しさん@お腹いっぱい。2009/03/04(水) 23:31:09
cshのこと聞いてもいいですか?
0295名無しさん@お腹いっぱい。2009/03/05(木) 00:18:50
>>1を読んでて答える人がいればいいんじゃない?
俺はcshは分からんが。
0296名無しさん@お腹いっぱい。2009/03/05(木) 02:03:59
変数の最後入っている改行コードを取り除く方法ってありますか?
Perl の chomp をシェルでやりたいのです。
0297名無しさん@お腹いっぱい。2009/03/05(木) 02:18:18
b="`echo $a`"
0298名無しさん@お腹いっぱい。2009/03/05(木) 02:21:31
b="$(printf "%s" "$a")"すると連続した空白も保存
0299名無しさん@お腹いっぱい。2009/03/05(木) 06:46:31
>>297 だとスペースが保存されないし、* とかの特殊記号が展開される。

b=`echo "$a"`
で桶。
0300名無しさん@お腹いっぱい。2009/03/06(金) 00:52:11
>>295
ではだめもとで。

配列の
array=( "a 1" "b 2" "b 3")
をforで1要素づつ使いたい場合

for d in ${array[@]}
do
echo $d
done

とかできますよね

これをcshでやること可能ですか?
0301名無しさん@お腹いっぱい。2009/03/06(金) 01:36:18
間違えた
for d in "${array[@]}"
do
echo $d
done

こうです。
0302名無しさん@お腹いっぱい。2009/03/06(金) 06:41:00
foreach i ($array)
echo $i
end
だろ。
0303名無しさん@お腹いっぱい。2009/03/06(金) 06:48:04
csh(笑)の質問はこっちでやれ
http://pc11.2ch.net/test/read.cgi/unix/1094041299/

>>302
それだと、要素の中のスペースで分割されてしまうからダメ。
例: "a 1" が a と 1 に別れてしまう。
0304名無しさん@お腹いっぱい。2009/03/06(金) 09:42:48
そんなこと言うならbash()笑の質問もこっちでやれってことになるぞw
http://pc11.2ch.net/test/read.cgi/linux/1210999497/
0305名無しさん@お腹いっぱい。2009/03/06(金) 22:26:43
>>300
cshなら配列使えばいいのでは?

#!/bin/csh -f
set a = ("a 1" "b 2" "c 3");

set i=1
while ( $i <= $#a )
   echo $a[$i]
   @ i = $i + 1
end
0306名無しさん@お腹いっぱい。2009/03/07(土) 00:49:25
set name = value
とかイコール前後にスペース付けられるあたりはcsh悪くないよね

というかスペースを許さないbashの代入がちょっとどうかと思う。
0307名無しさん@お腹いっぱい。2009/03/07(土) 01:10:08
なぜそこでbash
0308名無しさん@お腹いっぱい。2009/03/07(土) 03:17:01
とつぜんbashがきたので・・・
0309名無しさん@お腹いっぱい。2009/03/07(土) 07:01:04
>>306
算術式ならbashでもスペースを入れられるよ。

((i = 123))
echo $i
0310名無しさん@お腹いっぱい。2009/03/08(日) 04:05:42
(())ってなんなの?
0311名無しさん@お腹いっぱい。2009/03/08(日) 05:48:05
ま○こ
0312名無しさん@お腹いっぱい。2009/03/09(月) 19:53:57
まi = 123こ
echo $i
0313名無しさん@お腹いっぱい。2009/03/10(火) 07:44:38
sh, bashでシェル変数の値を変数名とするシェル変数を定義して
代入したいのですがどうすればよいでしょうか?
eval "$A=B"

eval "$A"=B
と書くと、意図通りに代入と判断されるシェル(最近のLinuxのbashやSolarisのsh)も
有ればコマンドと判断されてcommand not foundとなってしまう
シェルもあって、困っています。
0314名無しさん@お腹いっぱい。2009/03/10(火) 08:24:35
>>313
一般的には、代入する値のスペースや記号の解釈を避けるには、

eval $A=?''代入する値'?'

と書いておけば桶。evalを含めた2回の解釈を回避するために、
シングルクォートを2回ネスティングする。
$Aの方は、中身は単純な変数名が入っているため、
裸の $A のままクォートしなくても桶。

Solarisのshで動くならそれが標準と考えて良い。
これで動かないようなシェルは捨てるべき。
0315名無しさん@お腹いっぱい。2009/03/10(火) 08:27:12
>>313
わ、なぜかこの環境から書き込むと、
半角の\が?に化ける。(なんで?)
>>313 の?はバックスラッシュに読み変えてね。
0316名無しさん@お腹いっぱい。2009/03/10(火) 08:59:21
>>313
具体的にどのシェルか言えよ
そのときだけ"$A"にスペースが入ってんじゃないの?
0317名無しさん@お腹いっぱい。2009/03/10(火) 18:05:12
シェルスクリプトってOOじゃないんでしょ?
ダサっ
0318名無しさん@お腹いっぱい。2009/03/10(火) 18:37:45
>>313
困っています、じゃあ独り言にしかなってないぞ。
動かない場合の代わりの方法が欲しいのか、
ネタを流してるのかハッキリしろ。
0319名無しさん@お腹いっぱい。2009/03/10(火) 20:10:54
last(1)を去年の11月から今日まで出したいのですがどうすれば
いいでしょうか。
0320名無しさん@お腹いっぱい。2009/03/10(火) 20:30:06
cat /var/log/wtmp.3 /var/log/wtmp.2 /var/log/wtmp.1 /var/log/wtmp.0 /var/log/wtmp >/tmp/wtmp
last -f /tmp/wtmp
rm -f /tmp/wtmp

場所が違えば適宜探すこと。
圧縮されてたら適宜伸長すること。
11月の分が存在しなければ諦めること。
0321名無しさん@お腹いっぱい。2009/03/11(水) 02:00:46
>>314-315
ありがとうございます。
が、試してみたところエラーとなりました。

XX=YY形式の設定ファイルをIFS="="として、
while readで読み込んで、環境変数XX=値YYとしています。
whileブロックの外ではエラーがでないので、
IFS="="が悪さをしているのではないかとふと思いつきました。
明日試してみます。

>>316,318
bash3.2.25です。
0322名無しさん@お腹いっぱい。2009/03/11(水) 06:29:23
>>321
エラーになってあたりまえだ。

IFS="=" にすれば、コマンド上では = が消えてしまう。
XX=YY は、実際には XX YY という風に実行され、エラーになる。

これは、「シェル変数の値を変数名とするシェル変数を定義して代入」
以前の問題。

「シェル変数の値を変数名とするシェル変数を定義して代入」の問題なら、
>>314-315 の回答で合ってる。

あと、bash-3.2.25かどうかは関係ないと思うぞ。
エラーが出るなら他のシェルでもエラーになるはず。
0323名無しさん@お腹いっぱい。2009/03/11(水) 09:45:54
Windows PowerShellはOOなのに
シェルスクリプトはOOじゃないんだよね
時代遅れだね
0324名無しさん@お腹いっぱい。2009/03/12(木) 07:21:25
>>323
PowerShell は最近生まれたものなんだから当然だろ。
比較するなら PowerShell と同時期に生まれたシェルと比較しろ。
0325名無しさん@お腹いっぱい。2009/03/14(土) 01:53:46
jpgファイルのサイズを知りたいんですが、調べられますか?
0326名無しさん@お腹いっぱい。2009/03/14(土) 02:09:29
はい
0327名無しさん@お腹いっぱい。2009/03/14(土) 02:14:51
>>324
彼はLinux板のシェルスクリプトのところでも同じことを書いてたから。
0328名無しさん@お腹いっぱい。2009/03/14(土) 02:20:53
>>325
imagemagickのidentifyコマンド
0329名無しさん@お腹いっぱい。2009/03/14(土) 12:03:01
ls -lとかじゃないのか。
0330名無しさん@お腹いっぱい。2009/03/14(土) 12:32:29
echo "jpgファイル" | wc -c
0331名無しさん@お腹いっぱい。2009/03/14(土) 23:02:45
>>328
ありがとうございます。できました。

>>329
>>330
すいません。サイズという表現微妙でした。
解像度?1280x1024とかの値の話でした。
0332名無しさん@お腹いっぱい。2009/03/17(火) 22:56:18
かなりてきとーだけど。

while read l; do
for w in $l; do
type $w > /dev/null 2>&1 && echo $w
done
done < (ファイル) | sort | uniq
■ このスレッドは過去ログ倉庫に格納されています