シェルスクリプト総合 その19at UNIX
シェルスクリプト総合 その19 - 暇つぶし2ch431:名無しさん@お腹いっぱい。
12/03/05 22:52:03.41
続き
コンパイルに失敗した場合、Ctr-Cを入力すると
次のファイルにコンパイルをかけるようにしたいのですが、
--------------------------------------------
#!/bin/sh
# プログラム、コンパイルオプション一覧リストを指定
LIST=/home/shell/TESTLIST
# コンパイラのパスを設定
CCOM=/home/shell/cc.sh
# Ctr-Cを無視するように設定(サブシェルには有効)
trap : 2
# コンパイルをかける
while read ARG1 ARG2
do
#サブシェル化
(${CCOM} ${ARG1} ${ARG2})
done < ${LIST}
---------------------------------------------
でオッケーでしょうか?
ちなみにMakeは使用不可です。また、cc.shはいじれません。


432:名無しさん@お腹いっぱい。
12/03/06 11:06:00.37
>ちなみにMakeは使用不可です。また、cc.shはいじれません。

この状況を何とかした方が建設的かと。


433:名無しさん@お腹いっぱい。
12/03/06 19:10:20.96
>>431
> でオッケーでしょうか?
つまり俺たちにデバッグしろと言っているのか?

434:名無しさん@お腹いっぱい。
12/03/06 19:12:06.02
はい

435:名無しさん@お腹いっぱい。
12/03/06 19:19:26.97
はいじゃないだろうが!

436:名無しさん@お腹いっぱい。
12/03/06 19:21:31.59
はいじゃないが

437:名無しさん@お腹いっぱい。
12/03/06 20:23:39.44
はいはい。

438:名無しさん@お腹いっぱい。
12/03/06 21:07:07.27
>>429
コンパイルに失敗した場合、「N」や「Y」を入力しても反応がない原因を
教えてやる。

>>429 の while do .. done ループで、done < ${LIST} となってるので、
標準入力が ${LIST} にリダイレクトされたままになってて、
その状態で cc.sh が起動されてる。
cc.shの中でキーボードを読んでるつもりが、${LIST}を読んでしまうので、
「N」や「Y」を入力しても反応しない。

解決方法は、>>429 で、

----------------------------
exec 3< ${LIST}
while read ARG1 ARG2
do
${CCOM} ${ARG1} ${ARG2}
done 0<&3
----------------------------

とすること。標準入力をキーボードにしたまま、readには記述子3を読ませる。

439:名無しさん@お腹いっぱい。
12/03/06 21:12:06.05
>>438
おいおい、そのリダイレクト方法だと結局同じ理由で駄目だよ。

標準入力を退避しておいて復帰する。

exec 3<&0
while read ARG1 ARG2
do
${CCOM} ${ARG1} ${ARG2} 0<&3
done < ${LIST}

440:名無しさん@お腹いっぱい。
12/03/06 21:17:04.64
>>439 の方法でもいいが、
>>438 が言いたかったのは
↓じゃないかな

exec 3< ${LIST}
while read ARG1 ARG2 0<&3
do
${CCOM} ${ARG1} ${ARG2}
done

441:名無しさん@お腹いっぱい。
12/03/06 22:15:57.04
>431
> でオッケーでしょうか?
オッケーだと言う人がいたらしいよ。

ただし私は、貴方の環境と責任を共有していないので、自己責任でやって下さいね。

442:名無しさん@お腹いっぱい。
12/03/07 00:36:49.85
テキストから読み込んだ文字列内の「\\」をそのまま変数に入れたり表示させたりする方法を
探しています。OSはCentOS6、シェルはbashです
以下のような問題に対処したいのですが、何か手段はありますでしょうか?

以下のsampletext.txt(「\\」や「\」を含む)を、readecho.shのようにreadで読み、
echoで出力すると、「\」がエスケープか何かされているようで、表示されません
bashやechoのmanにある-Eオプションを明示的に付与してみても変化が無いようです

awkprint.shのようにawkで行うと期待した結果が出るのですが、他の処理の関係上、
できればawkは使わずに、シェルスクリプトで実現させる方法を知りたく思ってます
テキストを事前に「\\」から「\\\\」としておく等の対処はせずに済ませたいです

$ cat sampletext.txt
\\winsv\a\b\c
\\sambasv\d\e\f

$ cat readecho.sh
#! /bin/sh
while read STRING
do
echo -E "${STRING}"
done < sampletext.txt
$ ./readecho.sh
\winsvabc
\sambasvdef ←「\\」が「\」になり、「\」が消えている。NG

$ cat awkprint.sh
#! /bin/sh
cat sampletext.txt | awk '{print $0}'
$ ./awkprint.sh
\\winsv\a\b\c
\\sambasv\d\e\f ←上記のような問題はない。OK

443:名無しさん@お腹いっぱい。
12/03/07 00:42:21.68
>>442
read -r

444:名無しさん@お腹いっぱい。
12/03/07 00:42:48.66
つread -r

445:名無しさん@お腹いっぱい。
12/03/07 00:45:02.83
普通はread -rだけどbashは知らん。

446:名無しさん@お腹いっぱい。
12/03/07 00:48:20.73
>>443-445
情報ありがとうございました
うまくいきました
bashでもreadは「Backslash does not act as an escape character.」だそうです
なるほどreadで対処するのか...

$ cat readecho.sh
#! /bin/sh
while read -r STRING
do
echo -E ${STRING}
done < sampletext.txt

$ ./readecho.sh
\\winsv\a\b\c
\\sambasv\d\e\f

447:名無しさん@お腹いっぱい。
12/03/07 00:55:51.24
>>446
> bashでもread -rは「Backslash does not act as an escape character.」だそうです

と書きたかったのか?


448:名無しさん@お腹いっぱい。
12/03/09 22:27:14.08
AとBの処理があって、

Aを開始、
Bを開始
Bの中でAの処理中を待つことできますか?
意味わかりませんかね・・・
mkdirとかロック待ちみたいなやつです。




449:名無しさん@お腹いっぱい。
12/03/09 22:43:33.00
ロック待ちがわかるんなら、そのまんま A で mkdir lock して B で [ -d lock ] かければ?
while 文で無限ループ作って、sleep でも挟めば十分「処理待ち」になると思うけど。


450:名無しさん@お腹いっぱい。
12/03/09 22:44:29.80
>>448
FreeBSDなら lockf(1)、Linuxならflock(1)を使ってなんとかしろ。

451:名無しさん@お腹いっぱい。
12/03/09 23:06:08.54
>>449-450
ありがとうございます。
がんばってみます。


452:名無しさん@お腹いっぱい。
12/03/09 23:18:55.14
>>450
なんで似てるようで違う名前なの?

453:名無しさん@お腹いっぱい。
12/03/10 00:14:30.88
カレーライスとライスカレーみたいなモン

454:名無しさん@お腹いっぱい。
12/03/10 09:50:04.49
うまいなあ。それイタダキマス。

455:名無しさん@お腹いっぱい。
12/03/11 03:13:24.48
a=0
for FILE in `find / \( -iname "zoo*.png" -o -iname "land*.png" -o -iname "zoo*.txt -o -iname "land*.txt" \)`; do
rm -vf $FILE
echo $a
done
初心者です、スクリプト書いてみたんですが、この$aで表示される数がおかしくてこまってます。
なぜかrmコマンドでは1つも削除されておらずメッセージも表示されていないのに4と表示されるのです。
やりたい事としてはこうです↓

「zoo*.png、land*.png、zoo*.txt、land*.txtというファイル名のファイルを全て削除し、その数をカウントする」

何がおかしいのでしょうか?

456:名無しさん@お腹いっぱい。
12/03/11 04:32:12.07
>>455
4が表示されるのはオカルト。君もうすぐ死ぬんじゃない?
ファイルを削除して数をカウントしたいだけなら

find ほにゃらら -print0 | xargs -0 rm -v | wc -l

でよい。変数もforも必要ない。
4が出るのは君がオリジナルのスクリプトをここにコピペするときに何か端折ったせいだろう。

457:名無しさん@お腹いっぱい。
12/03/11 04:53:51.30
>>456
ごめんなさい、a=$(($a + 1))が抜けてました...

にしてもこんなにコンパクトになるもんなんですね
ありがとうございました

458:名無しさん@お腹いっぱい。
12/03/11 08:05:01.28
xargsは原始人の道具。
find ほにゃらら -exec rm -v {} + | wc -l
で良い。

459:名無しさん@お腹いっぱい。
12/03/11 08:11:05.46
-deleteが使えるfindもある
find ほにゃらら -delete -print | wc -l

460:名無しさん@お腹いっぱい。
12/03/11 08:14:18.54
>>458
-exec の方が古い感覚だけどどうなんだろ?

461:名無しさん@お腹いっぱい。
12/03/11 08:17:25.43
>>460
-exec ';' なら古い感覚
-exec + は新しい感覚

462:460
12/03/11 08:29:08.31
>>460
+ はいま使っているマシンの中では使えない物がほとんどかも。

-exec は元々 Unix に魅せられたポイントなので、1989 年には使ってた。
xargs はネットで教えてもらって 1995 年頃から使い始めた。
けど確か元からあったかも。

463:名無しさん@お腹いっぱい。
12/03/11 08:32:05.19
>>462
-exec + はSolarisでさえ使えるのに、どんな古いOS使ってるんだよ?

464:名無しさん@お腹いっぱい。
12/03/11 08:54:41.56
POSIXにも入っていてSVR4由来(当然Solarisにもある)でHP-UXにもあるのに、
使えないのを探す方が難しいよね。
原始人と言われたからってムキになってウソを教えるのは良くないな。

URLリンク(www.pasc.org)
| One of these extensions, which I believe is supported at least on all
| systems derived from SVR4 and on HP-UX (although in some cases it is an
| undocumented feature), is a variant of the "find -exec" primary where
| "find" does argument aggregation internally:
|
| find . -type f -exec some_command {} +

465:名無しさん@お腹いっぱい。
12/03/11 09:52:56.43
ちょっと前までテンプレにfindの項があったと思うが、今は無くなってるな。
確かテンプレではfind -print0 | xargs -0推奨で、スレ内議論では-exec +を使えと主張する人がいた。

466:名無しさん@お腹いっぱい。
12/03/11 10:09:06.10
テンプレにあったのはfind -print | xargs という回答には必ず言いがかりが付け
られていたから。質問者のためではなく回答者のためのテンプレ。
-exec {} + 構文が紹介されてからはxargsを使う意味がなくなったのか削除された。

それでもしばらくは-exec {} + を知らない原始人がいたけど、そのたびに原始人と
呼ばれて、絶滅していった。テンプレから削除されたのはこの時点(絶滅後)かも。

-exec {} + ですべてが置き換え可能とは言わないが、find+xargsが必要になること
は極めてまれ。

467:名無しさん@お腹いっぱい。
12/03/11 10:32:32.19
うーむ、結局その2つ違いって何ですか?

あと、パイプで繋がってしまっているrmを画面にも出力する方法ってないんでしょうか?

468:460
12/03/11 10:44:50.32
俺が xargs 教えてもらった頃は
-exec は fork するから良くないと言われてた。

+ は SVR4 に入っているのなら俺のもだいたい動くね。
でも俺まだ Tower の SVR2 や SVR3 とも格闘してるから。
ファイル名の長さが 14 文字までのやつ。

469:名無しさん@お腹いっぱい。
12/03/11 10:44:55.57
>>467
2つの違い
-print0や xargs -0は使えないOSがある。

>パイプで繋がってしまっているrmを画面にも
tee

470:名無しさん@お腹いっぱい。
12/03/11 10:55:09.82
>>467
1 find -exec \; 構文ではファイル一つ毎に別プロセスが起動されるので効率が悪い。
2 そこでまとめて処理できるようxargsが作られた。初出はPWBだからかなり古い
find -print | xargs
3 ファイル名に改行入れられるとヤバいので-print0, -0が設けられた
 find -print0 |xargs -0
4 そんな面倒な事しなくて済むように-exec {} + 構文が作られた
 -exec \; 構文と違い、別プロセスは(MAX_ARGSを考慮して)まとめて実行される。

> あと、パイプで繋がってしまっているrmを画面にも出力する方法ってないんでしょうか?
find ほにゃらら -delete -print |tee /dev/tty| wc -l
find ほにゃらら -exec rm -v {} + |tee /dev/tty| wc -l

471:名無しさん@お腹いっぱい。
12/03/11 10:56:05.20
> -print0や xargs -0は使えないOSがある。

例えば?

どっちも相当昔からある気がするけど

472:名無しさん@お腹いっぱい。
12/03/11 10:58:21.95
>>471
ちょっとは自分で調べろよ。Solarisで-print0等が使えないのは常識。

473:460
12/03/11 11:04:39.92
>>470
+ 便利そうだな。

474:名無しさん@お腹いっぱい。
12/03/11 11:06:35.90
-0はFreeBSD 2.1.5-RELEASEにはない。FreeBSD 2.1.6.1-RELEASEにはある。
相当昔といえば言えなくはないが。

URLリンク(www.freebsd.org)

URLリンク(www.freebsd.org)

475:名無しさん@お腹いっぱい。
12/03/11 11:22:05.20
結局、自分が使ってるOSで使える方法を使えって結論になってるよね毎回

476:名無しさん@お腹いっぱい。
12/03/11 11:29:54.60
答える側は質問者の環境を想像すべきだな。
SVR[23]のような骨董環境前提の回答なんか意味ない。

477:名無しさん@お腹いっぱい。
12/03/11 11:38:38.97
それなら結局xargsでも-exec +でもどっちでも良いんじゃない?十分に新しいLinux/*BSD環境前提なら。
自分はタイプ数の多いxargsは使わないけどね。
無用な-exec \;と-0無しのxargsさえ避ければ良い。
そもそも今回は-deleteが使えるならxargsも-exec +も要らないし。

478:名無しさん@お腹いっぱい。
12/03/11 11:42:53.84
>>477
だから、使える方法を使えばいいってことでしょ?
結論見えてないの?

479:名無しさん@お腹いっぱい。
12/03/11 11:51:09.25
>>469>>470
できました!!ありがとうございましたm(_ _)m

480:名無しさん@お腹いっぱい。
12/03/11 15:05:46.64
>>470
> 3 ファイル名に改行入れられるとヤバいので-print0, -0が設けられた

改行というか、広い意味での空白($IFS)だな。

481:名無しさん@お腹いっぱい。
12/03/11 15:27:32.53
xargsは、$IFSの改行/スペース/TABだけじゃなく、
シングルクォート/ダブルクォートも解釈しちゃうという問題がある。

it_don't_mean_a_thing.mp3

とかのファイル名もそのまま通らない

482:名無しさん@お腹いっぱい。
12/03/11 20:30:34.37
こういうイヤーンなファイル名があるときって、makeが通らなくなって難儀する。
コロン(:)が含まれてるファイル名なんか最悪。。
FILES = $(wildcard *.mp3)

$ make hoge
Makefile:〓: *** multiple target patterns. Stop.

483:名無しさん@お腹いっぱい。
12/03/11 22:43:26.33
なんかもう素人の集団みたいになってるな

基本的な歴史としては>>470の通りなんだが
現代においてはfindで引っかるファイル数が数十万~数百万ということも珍しくなくなった
そしてそのような場合{} +では処理できない、というか渡された先が悲鳴を上げる
だから 5. としてxargsを-n付きで使うようになったわけ
>>481みたいな問題にもちゃんと解法はある、つーかググレカス

ゆえに{} +はファイルを渡す先が確実に処理できると確信できる場合だけ使うべきで
癖をつけるなら-print0 | xargs -0の流れが正しい
何か問題が起きてもxrgsにオプション足すだけで解決する

つーか、初期の頃はちゃんとそう説明する奴が居たはずだけどな…

484:名無しさん@お腹いっぱい。
12/03/11 23:15:55.26
>>483
> 現代においてはfindで引っかるファイル数が数十万~数百万ということも珍しくなくなった
> そしてそのような場合{} +では処理できない、というか渡された先が悲鳴を上げる

<limit.h>に従った正しいプログラムなら何の問題もないです。

> だから 5. としてxargsを-n付きで使うようになったわけ

これはあほなプログラム向けです。


485:名無しさん@お腹いっぱい。
12/03/11 23:18:50.93
不特定個数の引数をとれるという仕様にもかかわらず悲鳴あげるのはバグ。
引数の個数に制限がある場合にはxargs -nも有効だが、そんなヘナチョコ
コマンド出会ったことない、具体的には何?

486:名無しさん@お腹いっぱい。
12/03/11 23:24:03.91
>>483
その根拠は何?
URLリンク(pubs.opengroup.org)
> The size of any set of two or more pathnames shall be limited
> such that execution of the utility does not cause the system's {ARG_MAX}
> limit to be exceeded.

>>484
あほなプログラムの実例
URLリンク(savannah.gnu.org)

487:名無しさん@お腹いっぱい。
12/03/11 23:37:58.77
というわけで2006年以前のfindutilsを使う可能性がある人は、
バグがあるので -exec {} + はやめたほうがいいということになるのかな

488:名無しさん@お腹いっぱい。
12/03/12 07:42:10.36
>>483は渡された先が悲鳴あげるといっているので、それは違う。
もっとも、>>483がその区別をつけられないだけかも知れないが。

489:名無しさん@お腹いっぱい。
12/03/12 17:53:31.98
結局>>483はボケ老人のタワゴトって結論でいいですか?
・悲鳴あげるヘナチョココマンドの存在は不明
>>481のようなケースも-print0, -0で対処できるている。

490:名無しさん@お腹いっぱい。
12/03/12 18:00:08.91
>>489
>>481 はそういうことを言ってるんじゃない。
>>480 が $IFSだけが問題と言っているのでは誤解を生じるので、
それだけじゃなくクォートも、と言う話。

491:名無しさん@お腹いっぱい。
12/03/12 18:05:46.84
>>490
ボケ老人のタワゴトとは>>483の↓この発言。>>481の指摘は正しい。
> >>481みたいな問題にもちゃんと解法はある、つーかググレカス

492:名無しさん@お腹いっぱい。
12/03/12 18:22:03.41
まあxargs対策でエスケープすればいいんだから、findの出力をfilterするなり解法はあるわな。

> 何か問題が起きてもxrgsにオプション足すだけで解決する

こっちのほうが問題では。

493:名無しさん@お腹いっぱい。
12/03/12 18:28:41.55
GNU findutilsは、デリミタを指定すると(-d, -0)、quoteは無視するようになっている。
他のfindは使ってないので知らないが。

494:名無しさん@お腹いっぱい。
12/03/12 18:29:11.30
print0でNUL文字を区切りにしたんだから、ファイルシステムに
許されているいかなる文字もこれで対応でしょ。

> 何か問題が起きてもxrgsにオプション足すだけで解決する
その問題とは? >>483のボケた脳内にある悲鳴あげるコマンド
しかないのですよ。

495:名無しさん@お腹いっぱい。
12/03/12 19:10:17.94
今までなかったからこれからもないと信じるのはどうなのと思わなくもない

496:名無しさん@お腹いっぱい。
12/03/12 19:15:52.59
>>483の脳内には現実に存在するみたいですよ。

497:名無しさん@お腹いっぱい。
12/03/12 22:17:38.36
お前らって、本当、どうしようもないバカだよな

ちったぁ議論らしいことをしたいなら、前提について定義しろよ

お前ら何のOSの事を想定してんだ?Solarisか?AIXか?386BSDか?バージョンは?え?
使ってるコマンドはどこの物だ?OSについてきたコマンドか?GNUのやつか?バージョンは?え?

そこが全然明確じゃないから、いっつもいっつもループしてんのか前に進んでんだか
前にも進んでないんだか分からねえグダグダ展開になってんじゃねえか

お前らの脳内それぞれで、前提狂った状態で、全然違うOSの事で話をしてたって、
意味も価値も実りある結論も、何もありゃしねえんだよ

お前らって、本当、どうしようもないバカだよな

498: 忍法帖【Lv=2,xxxP】
12/03/12 22:21:20.93
結局どっちがいいの?
find . -print0 | xargs -0 -I{} mv -vb {} ../tmp

とかした時って同名なのにバックアップ取られないファイルがあったんだけど、-exec +ならちゃんとバックアップされる?

499:名無しさん@お腹いっぱい。
12/03/12 22:24:10.73
>>497
バカからも得られるものはあるものさ

バカってのはこういう事を考えてるんだ、こんな風に誤解してるんだ、その程度しか知らないんだ、
じゃあ分かってない人はその辺が分かっていないのかもしれないから、ちょっと注意しよう

そんな目線での考察や気づきは、やっぱりバカからしか得られないものなのさ

500:名無しさん@お腹いっぱい。
12/03/12 22:33:58.20
分かりやすい自演

501:名無しさん@お腹いっぱい。
12/03/12 22:37:33.62
>>498
find、xargs、mvの仕様、及びファイル名の状態(空白含んでるとか、日本語ファイル名だとか)次第

どんな名前のファイルがこようがこれなら何でもOKという万能包丁は、ぶっちゃけ無い

FAQにも割とマジで"Use Samba and explorer.exe"ともある

502:名無しさん@お腹いっぱい。
12/03/12 23:04:49.76
バックグラウンドで何かを起動すると、
ジョブ番号とPIDが表示されるじゃないですか。
あれって表示させなくする方法ってあるんでしょうか?

時間のかかる処理をバックグラウンドで走らせて
その間に別の処理をやって、waitで同期する、
みたいなことをやるスクリプトで、邪魔なんですよね。


503:名無しさん@お腹いっぱい。
12/03/12 23:08:46.69
>>498
両方使えば?っていう初心者の意見です

504:名無しさん@お腹いっぱい。
12/03/12 23:19:19.45
>>502
スクリプト実行しているシェルは何?

505:名無しさん@お腹いっぱい。
12/03/12 23:21:09.67
bourne shだったりcshだったり。
Solarisです。


506:名無しさん@お腹いっぱい。
12/03/12 23:30:30.20
csh使うのやめろ
shは出ない

507:名無しさん@お腹いっぱい。
12/03/12 23:46:04.45
>>497
>>1

508:名無しさん@お腹いっぱい。
12/03/12 23:46:40.54
>>498
やってみればわかるよ

509:265
12/03/13 00:27:03.89
>>508
find . -exec cp -vb ../tmp +

find: -exec: no terminating ";" or "+"
だって・・・

510:265
12/03/13 00:27:31.16
まちがえた
find . -exec cp -vb {} ../tmp +

511:名無しさん@お腹いっぱい。
12/03/13 04:25:42.37
結局、print0 とかが必要になるのは
Windows でファイルを処理しきれなかった時ばかりなので

Unix 上のコマンドじゃなく
Windows ネイティブな UNIX-Like tools が
完璧なファイル名対応出来ればいいんだけどな。

Unix 上ではそんなファイル作らない。

512:名無しさん@お腹いっぱい。
12/03/13 10:06:48.40
みんなそんなに移植性必要なの?

513:名無しさん@お腹いっぱい。
12/03/13 10:12:13.36
> 結局、print0 とかが必要になるのは
> Windows でファイルを処理しきれなかった時ばかりなので
違うよ。root権限で動作するスクリプトが毒食わせられないための用心。

514:名無しさん@お腹いっぱい。
12/03/13 10:38:44.75
>>512
移植性が必要ならシェルスクリプトなんて使わないよ

515:名無しさん@お腹いっぱい。
12/03/13 12:31:59.14
ワンライナー手打ちするだけならそれこそどうでもいいし
それ以上気を遣いたいんなら、単にLL使えばよくね
Perlなら昔から標準でfind2perlとかついてくるし

516:名無しさん@お腹いっぱい。
12/03/13 23:03:21.13
シェルスクリプトを作る際の考え方はある程度使いまわせるが、移植性は低いわな実際

まぁ考え方っつっても、それは別にシェルスクリプトでしか習得できない考え方ではないけれど

517:名無しさん@お腹いっぱい。
12/03/13 23:19:15.02
autotoolsの中の人に聞かせてあげたい

518:名無しさん@お腹いっぱい。
12/03/13 23:27:28.51
移植性のために数多くの制約に縛られるなんてのは、
シェルスクリプト的に本末転倒なことなのさ

519:名無しさん@お腹いっぱい。
12/03/13 23:30:41.17
いや、移植性を突き詰めていくとシェルスクリプトで全部やるという結論に至る。

520:名無しさん@お腹いっぱい。
12/03/13 23:50:33.10
幸か不幸か自分のやりたい作業はシェルスクリプトで済んでしまう。perlもpythonもいらない。
だから(個人的には)シェルスクリプト GREAT! だね。

521:名無しさん@お腹いっぱい。
12/03/14 03:14:56.05
質問です。
cp a.txt b.txt
というシェルスクリプトが書かれた『hoge.sh』をダブルクリックで実行した場合、
普通はなんの反応もなく、コピーが実行されます。
これを、実行されたコマンドを端末に表示させることはできるでしょうか?

はじめから端末内で
bash hoge.sh
とすればいいのですが、深い階層にあって面倒なので…。
それに、この場合も何のコマンドが実行されたのかが分かりません。

522:名無しさん@お腹いっぱい。
12/03/14 06:51:12.07
>>521
hoge.shに以下のように書いておく。

xterm -e sh -xc 'cp a.txt b.txt; set +x; echo -n Hit any KEY:; read key'

523:名無しさん@お腹いっぱい。
12/03/14 12:25:04.10
>>522
ありがとうございました m(_ _)m

524:名無しさん@お腹いっぱい。
12/03/14 23:14:00.92
tarって入力されたデータをそのままの順でアーカイブするけど
-Tで渡すファイル名をソートする意味ってあるかな?

525:名無しさん@お腹いっぱい。
12/03/15 18:42:17.16
tarはアーカイブの先頭からファイルを展開していく
遅いテープに書き込むときに、早めに参照したいファイルをアーカイブの先頭付近に書いておくと
早めに展開される

そんな特性があるので、その特性を活かすためにアーカイブするファイルの順序を指定することは、
意味がある

わざわざソートして渡してるなら、その特性を理解してないだろうから、意味ないだろう

526:名無しさん@お腹いっぱい。
12/03/15 21:04:05.76
どなたか↓わかる方、今週末中にお願いします。

──────────────────
不定個数の整数の引数を与えて実行すると,それらの整数のGCMとLCMを計算して
表示するようなシェルスクリプトを作成せよ.使用シェルは/bin/shとする.

【実行例】
$ ./kadai15.sh 12 20 24
GCM = 4
LCM = 120
──────────────────

527:名無しさん@お腹いっぱい。
12/03/15 21:51:58.41
GCMとLCMがわからん

528:名無しさん@お腹いっぱい。
12/03/15 22:02:52.24
lcmは最小公倍数だね。
gcmは最大公倍数? w

529:名無しさん@お腹いっぱい。
12/03/15 22:13:31.83
Greatest Common Measure
Least Common Multiple

>>528 はアホ

530:名無しさん@お腹いっぱい。
12/03/15 22:20:19.95
最大公倍数
最小公約数

531:名無しさん@お腹いっぱい。
12/03/16 00:21:54.70
本当にどうでもいいことだが、gcm ってメジャーなんでしょうか?
普通の数学では gcd が圧倒的で、gcm は数学教育の教科書でしか
見たことがない。

532:名無しさん@お腹いっぱい。
12/03/16 00:26:08.56
数学板で聞いたら。

533:名無しさん@お腹いっぱい。
12/03/16 00:49:16.79
URLリンク(en.wikipedia.org)
URLリンク(ejje.weblio.jp)


534:名無しさん@お腹いっぱい。
12/03/16 01:11:00.95
SEだが>>526がわからんくて死にたい。
整数と小数の判定ってシェルでどうやんの?

535:531
12/03/16 01:13:58.15
メジャーなんですねgcmだけに、と無理矢理言っておきます

536:名無しさん@お腹いっぱい。
12/03/16 05:58:58.34
gcd()
{
a=$1; b=$2
while [ $b != 0 ]; do
t=$(($a % $b)); a=$b; b=$t
done
echo $a
}
t=$1; shift
for i; do
gcd=`gcd $t $i`
lcm=$(($t * $i / $gcd))
t=$lcm
done
echo gcd:$gcd lcm:$lcm


537:名無しさん@お腹いっぱい。
12/03/16 07:15:25.61
>>536
不正解

引数 12 20 24 の時、
gcd:12 lcm:120 と表示される。

正しくは GCM = 4

あと、/bin/shでは動かない $(( )) とか

538:名無しさん@お腹いっぱい。
12/03/16 07:43:40.34
>>537
freebsd の /bin/sh で動いたが


539:名無しさん@お腹いっぱい。
12/03/16 07:54:03.72
>>538
>>1
>FreeBSDユーザは/bin/shの正体がashなので注意。

それより、GCMの計算が間違ってるので結局ダメ

540:名無しさん@お腹いっぱい。
12/03/16 07:54:54.99
>>536
posix 互換の /bin/sh なら実装してるんじゃね $((expression))
URLリンク(pubs.opengroup.org)


541:名無しさん@お腹いっぱい。
12/03/16 10:00:20.84
>>537
Solarisも/bin/shはkshになっちゃいましたよ、おじいちゃん

542:名無しさん@お腹いっぱい。
12/03/16 10:02:48.59
gcdだけ作って秋田。
gcd()
{
local a b r

if [ $1 -gt $2 ]; then
a=$1; b=$2
else
a=$2; b=$1
fi

r=$(( $a % $b ))
[ $r -eq 0 ] && { echo $b; return; }

gcd $b $r
}


543:名無しさん@お腹いっぱい。
12/03/16 10:09:40.85
>>541
なってねーよ。嘘書くな。

544:名無しさん@お腹いっぱい。
12/03/16 10:37:43.03
>>543
なってるよ。おじいちゃん用のshは/usr/sunos/bin/shに隠居しました。

545:名無しさん@お腹いっぱい。
12/03/16 10:41:42.83
>>544
なってないよ。
opensolaris ≠ solaris

あと、pdkshになってるopensolarisだとしても、
「正体はkshだから注意」ということで/bin/shのお題の回答としては不正解。

546:名無しさん@お腹いっぱい。
12/03/16 10:54:47.13
ぷぷぷ

547:名無しさん@お腹いっぱい。
12/03/16 10:59:30.51
Solarisなんていつまであるんだろうなぁ。

548:名無しさん@お腹いっぱい。
12/03/16 11:18:01.21
$((expression))がサポートされてなければexprに書き換えれば
すむ事だから大した問題じゃないよね。
多分、/bin/shってお題はcsh使うなカスって意味だろうね。

おじいちゃんはこんなところで重箱の隅つついてないで、外へで
てゲートボールのエースでも目指した方がいいよ。

549:名無しさん@お腹いっぱい。
12/03/16 11:18:28.78
gcd(){
i=$1
while [ $(($1%i+$2%i)) -ne 0 ];do i=$((i-1)); done
echo $i
}

g=$1
l=$1
while [ $# -gt 1 ]; do
shift
g=`gcd $g $1`
l=$((l*$1/`gcd $l $1`))
done
echo gcd=$g lcm=$l


550:526
12/03/16 11:44:30.22
>>548
>多分、/bin/shってお題はcsh使うなカスって意味だろうね。

違います。従来からの/bin/shを使えという課題です。

>大した問題じゃないよね
それでは課題として点がもらえません。
大した問題かどうかは関係なく、課題通りの答が必要です。

引続き回答をお願いします。
表示形式も含めて課題です。

551:名無しさん@お腹いっぱい。
12/03/16 12:16:37.52
User Environment Feature Changes - Transitioning From Oracle Solaris 10 to Oracle Solaris 11
URLリンク(docs.oracle.com)

552:名無しさん@お腹いっぱい。
12/03/16 12:19:43.22
あらkshからbashになったのね。> Oracle Solaris 11の/bin/sh

553:526
12/03/16 12:23:58.00
私の為に争わないでください
課題の回答だけお願いします

554:名無しさん@お腹いっぱい。
12/03/16 12:24:33.25
>>552
えっと……どこをどう読めばそうなるのかとても不思議


555:名無しさん@お腹いっぱい。
12/03/16 14:29:31.51
>>553
ちったぁ自分で考えろ

556:名無しさん@お腹いっぱい。
12/03/16 14:45:01.99
>>552
> The default shell, /bin/sh, is now linked to ksh93. The default user shell is the Bourne-again (bash) shell.

the default user shell ってのは useradd したときのデフォルトとかの意味だろうね。
/bin/sh は ksh93 だ。

557:526
12/03/16 14:45:06.16
時間が無い。早くしてください。
来週の月曜の朝10時までにお願いします。
過程とか不要です。答えだけ書いてください。

もし回答以外のことも書きたい場合はスクリプトを*で囲って
目立つようにしてください

書き方の例を示します

****************************
a = 3
x + y = 5
****************************


558:名無しさん@お腹いっぱい。
12/03/16 14:46:05.73
今それどころじゃないからちょっと黙ってて。

559:名無しさん@お腹いっぱい。
12/03/16 14:51:59.23
ここまで、
「宿題は自分でやれ」
「来年はちゃんと講義聞こうな」
なし

560:名無しさん@お腹いっぱい。
12/03/16 15:38:56.29
分からない人は黙っててください

561:名無しさん@お腹いっぱい。
12/03/16 18:41:04.43
>>560
それって、お前も黙らなきゃいけないんじゃないか?

562:名無しさん@お腹いっぱい。
12/03/16 18:44:07.77
すべて分かった上で言ってるんだよ。

563:名無しさん@お腹いっぱい。
12/03/16 18:45:05.35
****************************
#! /bin/bash

set -e

function gcd() {
local -i i j
for ((i="$1";; i--)); do
for j in "$@"; do
((j % i != 0)) && continue 2
done
echo "$i"
return
done
}

function lcm() {
local -i i=1 j
for j in "$@"; do
((i *= j / "$(gcd "$i" "$j")"))
done
echo "$i"
return
}

printf "GCM = %d\nLCM = %d\n" "$(gcd "$@")" "$(lcm "$@")"
****************************
空気を読んで? bashで。
大学生はもう春休みなはずだが、実習?
それともこれだけできれば単位が貰える系か?
# 今年は進級できるかなあ、自分。

564:名無しさん@お腹いっぱい。
12/03/16 18:47:50.70
>>563
だからぁ、bashじゃ駄目だっておっしゃってますが・・

565:名無しさん@お腹いっぱい。
12/03/16 21:19:30.14
>>548
> $((expression))がサポートされてなければexprに書き換えれば
> すむ事だから大した問題じゃないよね。
letは使えないの?

566:名無しさん@お腹いっぱい。
12/03/16 21:21:16.68
もうできてる人が何人もいるんです

3/19の10:00まで待つと書きましたが、前倒して3/17の16:30までとします

>>557 にあるフォーマットでお願いします

567:名無しさん@お腹いっぱい。
12/03/16 21:22:56.00
>>565
もちろんletも使えない。

568:名無しさん@お腹いっぱい。
12/03/16 21:41:50.80
>>563
最大公約数求めるのに引数デクリメントしながらすべて割って試すとか
総当たりの非効率アルゴリズム使ってボケるんなら、
最小公倍数でもインクリメントしながら順番に割って総当たりするアルゴリズムで
ボケるべき。

569:名無しさん@お腹いっぱい。
12/03/16 21:49:10.39
つか, /bin/sh って言ってる奴いるけど, どの時点でどの機能が入った
/bin/sh まで許せるんだ?

FreeBSD の ports で拡張機能すべて許可した v7sh では func(){}
すら Syntax error なんだが...

# 少なくとも ``#!/usr/bin/env bash'' くらいにしないと販促だ >>563


570:名無しさん@お腹いっぱい。
12/03/16 21:54:56.85
>>566
バカ共の相手が面倒になったので締め切りました。



やっぱりバカしか居ないんだな。

571:名無しさん@お腹いっぱい。
12/03/16 22:25:57.27
なりすまし多いね

572:名無しさん@お腹いっぱい。
12/03/16 22:27:13.29
>>557
できたよ。GCMとLCMの計算方法が対称的になるようにしたよ。
/bin/sh純正だ。アルゴリズムはウケ狙いだけどな。


#!/bin/sh

GCM=$1
while :; do
for i in "$@"; do
if [ `expr "$i" % "$GCM"` != 0 ]; then
GCM=`expr "$GCM" - 1`
continue 2
fi
done
echo GCM = "$GCM"
break
done

LCM=$1
while :; do
for i in "$@"; do
if [ `expr "$LCM" % "$i"` != 0 ]; then
LCM=`expr "$LCM" + 1`
continue 2
fi
done
echo LCM = "$LCM"
break
done

573:名無しさん@お腹いっぱい。
12/03/16 22:28:07.31
自演も多いよ

574:名無しさん@お腹いっぱい。
12/03/16 23:17:57.60
本人です

3/17 17:00までに提出しないと単位が足りなくなるのが分かったので質問してます

レポートに貼り付けるのは私がしますので、3/17の16:30までにお願いします
また他の皆さんについても、ソースにバグがないかどうか、早急なチェックとデバッグを
期待しています

>>557 にあるフォーマットでお願いします

575:名無しさん@お腹いっぱい。
12/03/16 23:25:20.31
そろそろ飽きたわ。もう十分釣れただろ

576:名無しさん@お腹いっぱい。
12/03/16 23:37:15.49
ていうかもうできてんじゃないの?確かめてないけど

577:名無しさん@お腹いっぱい。
12/03/16 23:39:45.15
編集前ディレクトリと編集後ディレクトリを比較して、
変更がないファイルを編集後ディレクトリから削除する
シェルスクリプトを書こうとしています。

diffをディレクトリ同士で実行し同名ファイルを探し
その同名ファイルをdiffし返値が空なら削除という操作を
再帰的に階層を掘って実行すれば良いと思うのですが、
どうも何から書けばいいのか詰まってしまいました。

奇特な方居ましたらアドバイスお願いします。

578:名無しさん@お腹いっぱい。
12/03/16 23:45:20.44
>>577
まず、man diffをちゃんと嫁

579:名無しさん@お腹いっぱい。
12/03/17 00:14:42.67
>>578
オプションよく読んでいませんでした。
読んで出直してきます。ありがとうございました。

580:名無しさん@お腹いっぱい。
12/03/17 05:25:42.88
>>577
目的に対する作業の方法が間違ってる気がする。

何のために「編集前ディレクトリと編集後ディレクトリを比較して、
変更がないファイルを編集後ディレクトリから削除する」のか
を書いた方が、適切な答えが帰ってくると思う。

581:名無しさん@お腹いっぱい。
12/03/17 07:12:42.07
>>577
ひな形っぽいもの。階層が一つだけだからヒントにしかならんだろうけど。変数は出鱈目。
やりたいことのイメージは、こんなもんでしょ?

# mkdir /tmp/mae
# mkdir /tmp/ato
# MAE=/tmp/mae
# ATO=/tmp/ato
#
# touch $MAE/aaa
# touch $MAE/bbb
# cp -p $MAE/aaa $ATO/
# echo hoge > $ATO/bbb
#
# cd $ATO
# for ii in `ls`
> do
> [ -f $MAE/$ii ] && diff $ii $MAE > /dev/null 2>&1
> [ $? = 0 ] && rm $ii
> done
#
# ll $ATO
bbb

ちなみに HP-UX で検証。
ls > tmp.txt して while read LINE; do~done < tmp.txt とか LINE=`head $NUMBER tmp.txt | tail -1` でも目的だけは達成できる感じ。

582:526
12/03/17 07:30:38.91
>>572 さんありがとうございます。/bin/sh命令のみですね。
これで提出します。

583:名無しさん@お腹いっぱい。
12/03/17 15:36:57.64
>>572
こんなバカみたいな総当たりはダメだって言われちゃいました
もっと数学的な解法をアルゴリズム化したものでないとダメです
結果が正しければいいってレベルじゃないんです
100万とか1000万とか、それ位大きな値になると、ちっとも終わらないじゃないですか

期限は今日の16:40までとします

くれぐれもよろしくお願いします

584:名無しさん@お腹いっぱい。
12/03/17 16:12:07.29
>>583
できたよ。100万でも1000万でも、正しく実行すればすぐ終るよ。

#!/bin/sh

while :; do
echo -n 'Enter GCM = '; read GCM
for i in "$@"; do
[ `expr "$i" % "$GCM"` != 0 ] && { echo 'Try again'; continue 2; }
done; break; done
echo GCM = "$GCM"

while :; do
echo -n 'Enter LCM = '; read LCM
for i in "$@"; do
[ `expr "$LCM" % "$i"` != 0 ] && { echo 'Try again'; continue 2; }
done; break; done
echo LCM = "$LCM"

585:名無しさん@お腹いっぱい。
12/03/17 22:26:32.20
>>577
LANG=C diff -qrs a b の出力結果でなんとかする
というかバージョン管理システムを使うのが良い気がする

586:名無しさん@お腹いっぱい。
12/03/19 12:31:35.64
A=*.txt
B=$A
touch $B

とすると、"*.txt"というファイルが出来てしまうんですが
これ$Bを展開させたいときはどうすればいいんですかね

587:名無しさん@お腹いっぱい。
12/03/19 12:40:39.27
>>586
本当に >>586 のとおりに実行したのなら *.txt は展開される。
展開されないのはカレントディレクトリに *.txt にマッチするファイルがないから。
すでにファイルがなければ展開しようがない。

588:586
12/03/19 12:56:05.81
>>587
ヒントありがとうございます

oppai.txt がある場合⇒ oppai.txtにタッチ
oppai.txt がない場合⇒ *.txt を作成

という動きになりました
まーこれはこれで使い物になりませんわ

589:名無しさん@お腹いっぱい。
12/03/19 13:11:29.40
存在をチェックしてからtouchすればいいじゃない。

590:名無しさん@お腹いっぱい。
12/03/19 13:13:49.05
>>588
もし「存在しなければ作成したくない」という意図なら、

touch -c $B で桶。

591:名無しさん@お腹いっぱい。
12/03/19 13:45:15.79
>>586
エスパーすると、

A=*.txt
B=$A
mv $A /どこか
touch $B

みたいなことをやりたいのでは?

それなら、
A=`echo *.txt`
mv $A /どこか
touch $A

で桶。変数はAだけでよい。

592:586
12/03/19 14:20:52.93
>>590
天才や・・・ UNIX板には天才がたくさんいる
みんなありがとう

593:名無しさん@お腹いっぱい。
12/03/19 14:28:02.20
いや、みんなは普通だよ。

594:名無しさん@お腹いっぱい。
12/03/19 15:43:16.30
>>591のアホさが光るな。

595:名無しさん@お腹いっぱい。
12/03/19 15:45:13.28
>>586
これなんでBをはさんでるの?

596:名無しさん@お腹いっぱい。
12/03/19 17:56:07.30
おそらく A=*.txt で *が展開されなかったから
Bに代入し直せば再解釈されて展開されると勘違いしたのだろう

597:名無しさん@お腹いっぱい。
12/03/19 19:53:24.01
結局、どこで展開されたんだろうね

598:名無しさん@お腹いっぱい。
12/03/19 19:56:34.87
ん? A=*.txt でも B=$A でも 変数直接代入時は展開されないよ。
touch $B みたいにクォートなしで参照した時に初めて展開される。

599:586
12/03/19 19:58:57.99
>>598
ありがとう。それだけが心残りだったんだ

600:名無しさん@お腹いっぱい。
12/03/19 20:04:56.95
shを作ったBourneは天才だね。

601:名無しさん@お腹いっぱい。
12/03/19 20:08:20.98
あのソースコードは勘弁して欲しい。


602:名無しさん@お腹いっぱい。
12/03/19 21:12:40.16
ソース読んだのか あんたスゲーや

603:名無しさん@お腹いっぱい。
12/03/19 22:06:26.63
ソースコードつーか、これな。
URLリンク(minnie.tuhs.org)

604:名無しさん@お腹いっぱい。
12/03/20 08:01:57.14
URLリンク(x68000.q-e-d.net)
のサイトに、
#!/bin/sh
read input
if [ $input = 'q' ]; then
echo QUIT
fi
と言うシェルスクリプトを参考に
if [ "$input" = 'q' ]; then
と $input をダブルクォートで囲めばよい。しかしまだ落とし穴はある。たとえば "!" を入力すると、
[: =: unexpected operator
とまたしてもエラーになってしまう。これは "$input" が "!" であるため、
if [ ! = 'q' ]; then
として扱われたからだ。
ってありますけれど、何度!を入力しても、
[: =: unexpected operator
って表示されません。
それに、
$ test !c = 'q' ; echo $?
test cd /etc = 'q' ; echo $?
test: too many arguments
とエラーが表示されます。
どのような解釈をすると、!cがtest cd /etcに置換されるのでしょうか?

605:名無しさん@お腹いっぱい。
12/03/20 09:04:17.23
> [ ! = 'q' ]
これはそのように解釈するtestもあるから注意しろ。くらいでいいと思う。

> どのような解釈をすると、!cがtest cd /etcに置換されるのでしょうか?
ヒストリ置換だろ。

606:名無しさん@お腹いっぱい。
12/03/20 17:36:56.09
>>605
今の時代、そのエラーが出るshを使っている人、いるのかね?

607:名無しさん@お腹いっぱい。
12/03/20 17:41:15.64
今の時代、
[ ! = ! ]
[ [ = [ ]
[ ] = ] ]
[ = = = ]
[ -f = -f ]

など、すべて文字列の比較として期待通りに動作する

608:名無しさん@お腹いっぱい。
12/03/20 17:51:22.47
しかし未だに [ x"$hoge" = x"yes" ] などと書いてる人を見掛けるな
#!/bin/bashとか書いてるのに

609:名無しさん@お腹いっぱい。
12/03/20 19:57:58.15
スクリプトインジェクション対応だよ

610:名無しさん@お腹いっぱい。
12/03/20 21:45:56.60
[ "$hoge" = yes ] だとして具体的にどうインジェクトするんだよ

611:名無しさん@お腹いっぱい。
12/03/20 23:34:08.60
>>610

612:名無しさん@お腹いっぱい。
12/03/21 09:04:25.40
>>611
どうインジェクションするか解説お願いします

613:名無しさん@お腹いっぱい。
12/03/21 10:08:32.37
hoge=']; /bin/sh;'

614:名無しさん@お腹いっぱい。
12/03/21 10:47:17.62
ってゆーか、こういう場合は

case "$hoge" in
yes) ...;;
esac

って書くよね、ふつー。[Yy][Ee][Ss] なんかに変えるのも簡単だし。


615:名無しさん@お腹いっぱい。
12/03/21 11:14:27.91
>>613
>>610はダブルクオートで囲ってるから、[コマンドの第一引数として$hogeの中身が渡るんで、そのhogeの値はそのまま[コマンドが解釈する。
どうあがいてもインジェクションなんて無理だと思うんだが。

616:名無しさん@お腹いっぱい。
12/03/21 11:26:14.79
てきとーに言ったんだろ。
もうカンベンしてやれ。

617:名無しさん@お腹いっぱい。
12/03/21 12:19:06.39
本人乙

618:名無しさん@お腹いっぱい。
12/03/21 13:26:55.78
違うよ。

619:名無しさん@お腹いっぱい。
12/03/21 13:38:09.35
最近のJavaScriptのようにeval使いまくりで威張る奴か。

620:名無しさん@お腹いっぱい。
12/03/21 14:28:05.05
>>619
座布団

621:名無しさん@お腹いっぱい。
12/03/21 15:37:01.15
全部持ってって~

622:名無しさん@お腹いっぱい。
12/03/21 19:24:26.73
>>606
$ busybox ash
$ hoge=!
$ if [ "$hoge" = 'q' ]; then echo QUIT; fi
ash: q: unknown operand

623:名無しさん@お腹いっぱい。
12/03/21 22:56:44.16
URLリンク(uec.usp-lab.com)

>シェルスクリプトに制御構文が増えることを極力避けるように様々な工夫をしている。
>制御構文を避ける理由はコードが読みにくくなるためだ。
>これまで制御構文whileやforのはずし方について書いてきた。
>処理速度を高速化するためにwhileやforをコマンドに置き換えるというのは、
>それなりの効果が期待できる方法だ。
>シェルスクリプトに制御構文であるforやwhileが出てきたら、
>何か避ける方法がないか探してみるとより高速なスクリプトが書けるようになるかもしれない。
ってかいてあって、いろんな例が書いてあったり、
変なパッケージ(python製)を入れて、そのコマンドを使ったりしてるんですね。
僕は制御構文外すと逆に可読性がおちたり、
pythonで書かれたコマンドを呼び出すより、シェルスクリプトで制御構文書いた方が
早いと思うんですけど、おかしいですかね?

624:名無しさん@お腹いっぱい。
12/03/21 23:01:45.31
質問です。

以下のようなファイルがあるとします。
-----------------
1. aaa hello
2. bbb
3. ccc
4. ddd hello
5. ddd hello
6. eee hello
-----------------
このファイルの2行目から5行目に限定して、helloをgood byに変更したいです。
どのようなやりかたがありますでしょうか?
sedを使えばいいのかなと思うのですが。。



625:名無しさん@お腹いっぱい。
12/03/21 23:09:05.42
お前はマニュアル読むという事を考えたことが無いのか?

626:名無しさん@お腹いっぱい。
12/03/21 23:34:20.22
>>624
うん、sedの超基本的な使い方で出来る

627:名無しさん@お腹いっぱい。
12/03/21 23:34:53.13
sedを使えばいいと思うよ



628:名無しさん@お腹いっぱい。
12/03/21 23:41:30.82
>>623
そのページを見て思ったことは、xargsは便利だね、くらい

629:名無しさん@お腹いっぱい。
12/03/22 00:58:20.98
>>623
シェルスクリプトに限らず、プログラム書く時に(一部の)制御構文を使わないってのは個人的に良くやる。効率とか性能とか抜きで。
ゲームの縛りプレイみたいなもんだけど、意外なテクニックを発見したりできて楽しめるよ。おすすめ。
上司や同僚に見つかったら>>623のサイトみたいな適当なウンチクで誤魔化せばOK。



630:名無しさん@お腹いっぱい。
12/03/22 01:14:19.58
>>624
sed で 2行目から5行目は 2,5。
hello を good byに置換するには s/hello/good by/
接続すると 2,5s/hello/good by/


631:名無しさん@お腹いっぱい。
12/03/22 02:23:18.01
>>629
BASICのころはあったけどな。
if文分岐とかで速度差が出ないようにするとかで。
今はそういうのする必要ないけど。

632:名無しさん@お腹いっぱい。
12/03/22 08:22:33.32
PerlやC#、COBOL、Fortran、アセンブリなんかも、見慣れてなければ読みにくく
感じるものさ

633:名無しさん@お腹いっぱい。
12/03/22 08:28:41.72
Whitespaceもな。

634:名無しさん@お腹いっぱい。
12/03/22 09:18:49.18
俺はsedが嫌いなので、できるだけperlを使うようにしている

635:名無しさん@お腹いっぱい。
12/03/22 09:56:14.04
それは報告しなくてもいいです。

636:名無しさん@お腹いっぱい。
12/03/22 11:24:16.01
kshで待ち行列を作りたいんですが、どうしたらいいでしょう?

基本動作はキューなんですが、
1 2 3
↓1を実行
2 3

1 2 3
↓2を実行
1 3
としたいです

unset 配列[N]でインデックスを詰めてくれればこんなの楽勝なのに…

637:名無しさん@お腹いっぱい。
12/03/22 11:37:02.12
>>636
ファイルにしたらいい

638:名無しさん@お腹いっぱい。
12/03/22 20:00:10.46
位置パラメータ使う。

$ set -- 1 2 3 4
$ shift
$ echo $@
2 3 4
$ set -- 1 2 3 4
$ set -- $1 ${@:3}
$ echo $@
1 3 4



639:名無しさん@お腹いっぱい。
12/03/22 20:22:13.25
>>636
unset array[N] で要素をunsetした後に、

array=(${array[@]}) でセットしなおせばインデックスは詰まる。

>>638 とは違って位置パラメータを壊さずに済む。

640:名無しさん@お腹いっぱい。
12/03/22 21:29:35.34
>>639
かっこういい

641:名無しさん@お腹いっぱい。
12/03/23 22:05:53.20
シェルスクリプト学び始めたばかりの初心者です。

・ファイルを指定フォルダ内へコピー
・同名ファイルが存在する場合は、
既に存在するファイル名を「ファイル名 (1)」へ変更し、
既に「ファイル名 (1)」が存在しているのであれば、
それをさらに「ファイル名 (2)」へ変更し、、、(繰り返し)

というシェルスクリプトを書きたいんですが、

既に「ファイル名 (*)」が存在する場合に*の数字を
どのようにすれば知ることができますか?

*さえ知れたらexprを使えば出来るとは思うのですが...
アドバイスお願いします。

642:名無しさん@お腹いっぱい。
12/03/23 22:27:01.94
>>641
逆に考える。

変数iとかに1を入れておいて、

"ファイル名($i)" が存在したら
iをインクリメントして "ファイル名($i)" にリネームする。

643:名無しさん@お腹いっぱい。
12/03/23 22:28:54.51
再帰使わないとややこしいことになりそうだな。


644:名無しさん@お腹いっぱい。
12/03/23 22:32:05.36
最小の空きを使うんでいいの?
i=1; while [ -f "file($i).txt" ]; do i=`expr $i + 1`; done; echo $i

645:名無しさん@お腹いっぱい。
12/03/23 22:52:22.20
「それを」が何を指すかによる。


646:名無しさん@お腹いっぱい。
12/03/23 22:56:33.59
GNU cp なら --backup=numbered とか?

647:名無しさん@お腹いっぱい。
12/03/24 01:18:46.16
なんか見覚えがある処理だと思ったが logrotate かいな。

648:名無しさん@お腹いっぱい。
12/03/24 10:30:46.53
>>641
つまりアヌスを知りたいと……教えてあげよう

649:名無しさん@お腹いっぱい。
12/03/24 18:23:06.74
>>641
実機が無いので試せないけど・・・

第一引数:コピー対象ファイル名(絶対パス指定)
第二引数:コピー先ディレクトリパス

#!/bin/ksh
FILE_NAMEW=`basename ${1}`
COUNT=1
TARGET_FILE=${2}/${FILE_NAME}

if [[ -e ${TARGET_FILE} ]]; then
while true
do
if [[ -e "${TARGET_FILE}(${COUNT})" ]]; then
COUNT=`expr ${COUNT} + 1`
else
cp ${1} ${TARGET_FILE}(${COUNT})
break
fi
done
else
cp ${1} ${TARGET_FILE}
fi
exit 0


650:名無しさん@お腹いっぱい。
12/03/24 18:40:54.37
突っ込みどころ多いな

651:名無しさん@お腹いっぱい。
12/03/24 18:48:18.47
もっと単純にこうだろ。
第1引数: コピー元ファイル(絶対/相対path関係なし)
第2引数: コピー先ファイル(ディレクトリではない)

#!/bin/sh

FILE=$2

if [ -f "$FILE" ]; then
i=1
while [ -f "$FILE($i)" ]; do
i=`expr $i + 1`
done
FILE="$FILE($i)"
fi

cp "$1" "$FILE"

652:641
12/03/24 21:11:20.76
皆さんアドバイスありがとうございました。
642さんの意見を参考に書いていたら、
651さんとほぼ同じようなものが書けました。

勉強になりました!

653:名無しさん@お腹いっぱい。
12/03/24 22:20:08.70
その書いたものをさらしてくれると
みんなも勉強になるんだけどなぁ

654:名無しさん@お腹いっぱい。
12/03/24 22:34:45.96
#!/bin/bash

[ -e "$2" ]&&{ i=0; while [ -e "$2($((++i)))" ];do :;done; set "$1" "$2($i)";}
cp "$1" "$2"

655:名無しさん@お腹いっぱい。
12/03/25 10:39:31.72
rm -rf -- *
ってどういう風に解釈すれば良いんですか?
-- って正規表現ですか?
*はファイル名ですか?

656:名無しさん@お腹いっぱい。
12/03/25 10:59:50.45
>>655
その * は glob。シェルが解釈する。
シェルが展開して rm に渡す。

-- は正規表現でも何でもなくて、ただの --。
シェルは特に何もしない。
そのまま rm に渡される。

657:名無しさん@お腹いっぱい。
12/03/25 11:00:45.80
rm が -- をどう解釈するかは man rm に載ってるはず。

658:名無しさん@お腹いっぱい。
12/03/25 11:28:39.15
- で始まるファイル名(コマンドからはオプションに見える)に
マッチしたときのための策だな。


659:名無しさん@お腹いっぱい。
12/03/25 11:51:49.52
でも rm -- が使えるのは GNU rmだけだから、使わない方がいいな。

660:名無しさん@お腹いっぱい。
12/03/25 12:14:56.30
>>659
調べたらBSD系はgetopt(3)つこうてるから--大丈夫だよと書いてあったんだけど
他のUNIXはまた違うの?

661:名無しさん@お腹いっぱい。
12/03/25 12:24:48.03
BSD以外のUNIXってあるの?

662:名無しさん@お腹いっぱい。
12/03/25 13:38:40.68
ねーよんなもん

663:名無しさん@お腹いっぱい。
12/03/25 13:56:37.10
Solarisのmanには、BSDユーザーのために仕方なく -- が使えるようにしてあるが、
将来は -- が使えなくなるので注意、と書いてあるね。

664:名無しさん@お腹いっぱい。
12/03/25 18:55:04.62
ワイルドカードを使うときは
rm ./*
みたいにすれば引数の先頭が - になることはない。
--が使える保証がなければこっちで。

665:名無しさん@お腹いっぱい。
12/03/25 20:43:30.34
この手の問題って rmだけじゃなく cp mv ln等全部なんだよな。

で、-- が使えない ln で、-sという名前を指しているsymlinkを作ろうと、

ln -s ./-s hoge ってやると、hoge -> ./-s というsymlinkができて、
symlink自体に ./ が含まれてしまって美しくない。
-- が使えない条件で 、hoge -> -s は作れないものか。

666:名無しさん@お腹いっぱい。
12/03/25 22:24:57.35
リンク作る部分をスクリプト言語に投げるとかは?
じゃあ全部スクリプトでやれよみたいな話になりかねんからダメかね

667:名無しさん@お腹いっぱい。
12/03/25 23:41:27.50
>>664
昔からUnixやってる奴は普通そのやり方だよな
--指定してても、引数に./*でなく*を指定するのは違和感を感じる

668:名無しさん@お腹いっぱい。
12/03/26 06:20:04.43
特定のフォルダのpngファイルを見つけて

「◯◯◯.png」というファイルを見つけました

と表示させたいのですが、なるべくコンパクトにするにはどのようにすればいいでしょうか?
自分のやり方だとbasenameで失敗してうまく表示されません
あと、そのフォルダにpngファイルがなかった場合は何も表示しないようにしたいです。

find ${DIR}/ -name "*.png" -exec echo "「`basename {}`」というファイルを見つけました" \;


669:名無しさん@お腹いっぱい。
12/03/26 06:44:41.40
>>668
find "$DIR" -name '*.png' -printf '「%f」というファイルを見つけました¥n'

670:名無しさん@お腹いっぱい。
12/03/26 07:06:33.81
>>668
`basename {}`はfind実行より先に展開されてしまうので、
{}という文字列のbasenameが実行されて無意味になっているのが原因。

GNU findなら >>669 でよし。

671:名無しさん@お腹いっぱい。
12/03/26 07:46:41.98
>>668
find "$DIR" -name '*.png' -exec sh -c 'for f;do echo 「`basename "$f"`」というファイルを見つけました;done' - {} +

672:名無しさん@お腹いっぱい。
12/03/26 14:20:40.93
>>669>>670>>671
おかげさまでできました!
ありがとうございました!!

673:名無しさん@お腹いっぱい。
12/03/27 22:52:24.44
質問です。

開始日付と終了日付を指定したら、その間の日付を出力するスクリプトを作りたいです。
イメージとしては以下のような感じです。
$ ./hoge.sh -s 20120301 -e 20120303
20120301
20120302
20120303

以下の処理までは作ったのですが、ここから先が思いつきません。
---------------------------------------------
$ cat hoge.sh
#!/bin/sh

while getopts s:e: option
do
case $option in
"s")
start_date=$OPTARG
;;
"e")
end_date=$OPTARG
;;
*)
;;
esac
done
---------------------------------------------

よろしくご教示お願いします。


674:名無しさん@お腹いっぱい。
12/03/27 23:18:59.00
日付まわりはシェルでやるとめんどいから
perlとか使っちゃう。

675:名無しさん@お腹いっぱい。
12/03/27 23:30:44.14
> 以下の処理までは作ったのですが、ここから先が思いつきません。

dateをつかってこんな感じかな

ステップ1. 今日の日付を20120301のように出力しよう
ステップ2. 20120301のような日付を、UTCエポックからの秒数に換算しよう
ステップ3. UTCエポックからの秒数を、20120301のような日付に変換しよう
ステップ4. 20120301のような日付を受け取り、その翌日の日付を出力しよう
ステップ5. ループを回して指定範囲の日付を全て出力しよう

※UTCエポックは 1970-1-1 00:00:00 UTC

676:名無しさん@お腹いっぱい。
12/03/27 23:42:28.28
>>673
bash、GNU date依存

#!/bin/bash

while getopts s:e: opt; do
case "${opt}" in
's') stime=$(date -d "${OPTARG}" '+%s') ;;
'e') etime=$(date -d "${OPTARG}" '+%s') ;;
esac
done

t=${stime}

while (( ${etime} >= ${t} )); do
date -d @${t} '+%Y%m%d'
t=$(( ${t} + (60 * 60 * 24) ))
done

677:名無しさん@お腹いっぱい。
12/03/28 00:15:25.48
>>676
bashならこっち
for (( t = stime; etime >= t; t += 60 * 60 * 24 )); do
date -d @${t} '+%Y%m%d'
done


678:676
12/03/28 00:53:33.92
添削ありがとう

679:名無しさん@お腹いっぱい。
12/03/28 06:47:17.46
>>676 >>677 でOKだね。
そんな中、何の解答にもヒントにもなってない >>675 って・・・

680:名無しさん@お腹いっぱい。
12/03/28 06:56:04.85
>>676 >>677
わざわざepochからの秒数に直さなくても、日付だけで行けるよ。


#!/bin/bash

while getopts s:e: opt; do
case $opt in
s) stime=$OPTARG;;
e) etime=$OPTARG;;
esac
done

for ((t = stime; etime >= t; t=$(date -d "$t 1 day" '+%Y%m%d'))) {
date -d "$t" '+%Y%m%d'
}

681:名無しさん@お腹いっぱい。
12/03/28 07:04:16.81
>>680
forループ中、dateが1回無駄になってる。せっかく$tに入ってるのでそれ使え。

for ((t = stime; t <= etime; t=$(date -d "$t 1 day" '+%Y%m%d'))) {
echo "$t"
}

682:680
12/03/28 07:10:47.88
添削ども

683:名無しさん@お腹いっぱい。
12/03/30 14:34:15.36
標準出力に日付をつけたいんだけど
かっこいい方法ありますか?

684:名無しさん@お腹いっぱい。
12/03/30 14:51:40.88
エスパー、日本語解読しろ

685:名無しさん@お腹いっぱい。
12/03/30 14:55:44.65
>>683
#!/bin/sh

while IFS= read -r line; do
echo "`date`: $line"
done

686:名無しさん@お腹いっぱい。
12/03/30 15:42:18.34
>>685
ありがとうございます

687:名無しさん@お腹いっぱい。
12/03/30 15:44:45.94
        ∧∧
       ヽ(・ω・)/   ズコー
      \(.\ ノ
    、ハ,,、  ̄
     ̄

688:名無しさん@お腹いっぱい。
12/03/30 16:39:16.72
ていうかあの文章がわからないとかギャグだろ

689:名無しさん@お腹いっぱい。
12/03/30 16:44:05.09
もうcat --dateでいいよ。
誰かパッチを送れよ。

690:名無しさん@お腹いっぱい。
12/03/30 17:35:02.11
俺は
command > $(date +%Y%m%d)
って意味かとオモタ

691:名無しさん@お腹いっぱい。
12/03/30 18:02:04.91
>>690
目的はロギングだな、と想像できれば、毎行にタイムスタンプつけたいんだな
ということもわかる

692:名無しさん@お腹いっぱい。
12/03/30 18:09:51.47
>>691
目的はロギングだな、と想像できれば、ログファイル名毎に日付を入れたいんだな
と考えるのが自然

693:名無しさん@お腹いっぱい。
12/03/30 18:15:31.04
まぁもう解決したんだからそれでいいんじゃね。

694:名無しさん@お腹いっぱい。
12/03/30 18:27:01.79
俺は
touch -t YYMMDDhhmm /dev/stdout
って意味かとオモタ

695:名無しさん@お腹いっぱい。
12/03/31 01:35:03.44
俺はプロンプトに日時を入れるのかと…

696:名無しさん@お腹いっぱい。
12/03/31 04:56:25.93
自分はdate > /dev/tty みたいなことかと思った

697:名無しさん@お腹いっぱい。
12/03/31 17:23:45.97
>>680
それだと、1900年とかそれ以前とか、32bit版の場合の2038年以降が動かないし、
GNU dateに依存するのもいやだし、
dateコマンドに頼らずに20120301等のの数字を直接操作して計算する方法ないですか?

698:名無しさん@お腹いっぱい。
12/03/31 17:42:14.02
頑張って書けば可能だけど、
月の長さや閏年とか考えると、GNU dateかLL使うのがいいですよ。
コマンド組み合わせるのがシェルの得意なところだし。

699:名無しさん@お腹いっぱい。
12/03/31 17:47:43.69
>>698
GNU date使っても epoch以前の日付には対応できないだろ、って言ってるのでは?

700:名無しさん@お腹いっぱい。
12/03/31 18:35:51.33
昔のこと考えたって、そもそも日本が西暦になったのは明治からだぞ
calコマンドが表示してるのはイギリスの暦らしいね

$ cal 9 1752
September 1752
Su Mo Tu We Th Fr Sa
1 2 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30


701:名無しさん@お腹いっぱい。
12/03/31 18:48:26.54
>>700
江戸時代でもそれ以前でも年表は西暦で記述されてるから無問題。
1752年の件も含め、紀元1年以降対応できれば幸いです。
紀元前までは要りません。

702:名無しさん@お腹いっぱい。
12/03/31 19:29:56.45
localeをイタリアにしたら1582年に暦が切り替わる実装もあるのかな。


703:名無しさん@お腹いっぱい。
12/03/31 20:51:17.87
そのくらい前のデータはまだ完全に整備されてない。
↓こういうデータがあって、Common Lisp, Mathematica, Javaのライブラリがある。
Calendrical Tabulations, 1900?2200
Edward M. Reingold, Nachum Dershowitz
URLリンク(www.cambridgejapan.org)

けどまあ元のお題についてはGNU dateかLLでやるのがいいかと。

704:名無しさん@お腹いっぱい。
12/04/01 12:21:49.60
>>701
曜日はどうなのよ・・・

705:名無しさん@お腹いっぱい。
12/04/01 12:24:17.12
>>704
20120301 等の数字だけ処理できればいいので、曜日は無視でいいです。

706:名無しさん@お腹いっぱい。
12/04/01 13:39:02.95
>>704
曜日以外はできたのか。じゃあ早く回答してやれよ。

707:名無しさん@お腹いっぱい。
12/04/01 14:01:13.24
>>706
曜日以外は標準で対応し照るじゃん

708:名無しさん@お腹いっぱい。
12/04/01 14:02:48.07
>>707
epoch以前でも?

709:名無しさん@お腹いっぱい。
12/04/01 14:05:53.14
$ date -d "1 years ago"
2011年 4月 1日 金曜日 14:04:49 JST
$ date -d "100 years ago"
1912年 4月 1日 月曜日 14:04:55 CJT
$ date -d "200 years ago"
1812年 4月 1日 月曜日 14:05:08 CJT

できてんじゃん

710:名無しさん@お腹いっぱい。
12/04/01 14:09:36.73
>>709
環境依存なので却下

711:名無しさん@お腹いっぱい。
12/04/01 14:16:22.13
じゃあ環境に依存しない方法を自分で考えてくれ
「すべての環境」に対応するのは骨が折れると思うが
期待しているぞ

712:名無しさん@お腹いっぱい。
12/04/01 14:21:28.89
>>711
>>697 の言うように、20120301等の数字を直接演算すればそもそも環境依存しない。
その演算が場合分けとかでややこしいだけで。

713:名無しさん@お腹いっぱい。
12/04/01 14:36:54.89
>>709
GNU date epoch以前の閏年処理おかしいよ。

$ date -d 16000229 ← 1600年は閏年
Tue Feb 29 00:00:00 LMT 1600

$ date -d 17000229 ← 1700年は閏年
date: invalid date `17000229' ← 駄目じゃん

$ cal 2 1700
  February 1700 
Su Mo Tu We Th Fr Sa
       1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 ← 閏年だよ

714:名無しさん@お腹いっぱい。
12/04/01 16:31:55.42
>>713
グレゴリオ暦で1700年は平年です

$ man cal
> グレゴリオ暦への切り替えは 1752 年の 9 月 3 日に行われたと仮定している。

$ cal 9 1752
9月 1752
日 月 火 水 木 金 土
1 2 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

715:名無しさん@お腹いっぱい。
12/04/01 16:37:34.38
$ gcal --version | head -n 1
gcal (GNU cal) 3.6
$ gcal 2 1600; gcal 2 1700 ; gcal 9 1752

February 1600
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29


February 1700
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28


September 1752
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

716:名無しさん@お腹いっぱい。
12/04/01 16:47:02.18
>>714
1700年はまだグレゴリオ暦に切り替わってないのだから、
1700年は閏歳が正しい。

別の例として、
1500年は閏歳なのだが、
calでは閏歳(正しい)
GNU dateでは平年(間違い)

いずれにしても GNU dateでこの年代の日付処理はできない。

717:名無しさん@お腹いっぱい。
12/04/01 17:25:06.62
西暦年が100の倍数の時、
1700年以前なら単純にすべて閏年にする。
1800年以降の場合は、400の倍数でない年のみ平年に戻す。

で桶?

case文バリバリでだれかシェルで組んでくれ。

718:名無しさん@お腹いっぱい。
12/04/01 17:54:49.44
厳密にやるためには国や宗教の情報が必要になるので
あまりしゃかりきにならんでええ。
日本は1872年かな。

719:名無しさん@お腹いっぱい。
12/04/01 18:04:26.31
日本においては閏年の算定を皇紀を用いて行うことが法令で定められています

720:名無しさん@お腹いっぱい。
12/04/01 18:12:40.42
>>717
できた気がする。思ったより場合分け簡単だった。
1752年9月も対応

s_date=20120227 # 仮
e_date=20120305 # 仮

t=$s_date
while [ "$t" -le "$e_date" ]; do
echo "$t"
t=`expr "$t" + 1`
case $t in
????0[13578]32|????1032) t=`expr "$t" + 69`;;
????1232) t=`expr "$t" + 8869`;;
????0[469]31|????1131) t=`expr "$t" + 70`;;
????0230) t=`expr "$t" + 71`;;
17520903) t=17520914
esac
case $t in
????0229)
y=`expr "$t" / 10000`
case `expr "$y" % 4` in
0)
[ "$y" -le 1700 ] && continue
[ `expr "$y" % 400` = 0 ] && continue
[ `expr "$y" % 100` != 0 ] && continue
;;
esac
t=`expr "$t" + 72`;;
esac
done

721:名無しさん@お腹いっぱい。
12/04/01 19:24:47.68
>>720
西暦999年以前がダメ。頭に0付け加える処理が必要。

722:名無しさん@お腹いっぱい。
12/04/03 07:17:19.37
>>720-721
ありがとうございました

723:名無しさん@お腹いっぱい。
12/04/03 20:05:15.60
ファイルがあるかないかだけを調べる標準のコマンドありますか?
[ -f /tmp/unko ]
よりかっこいい方法募集

724:名無しさん@お腹いっぱい。
12/04/03 20:06:28.95
test(マテ


725:名無しさん@お腹いっぱい。
12/04/03 20:20:14.40
「標準のコマンド」とは?

726:名無しさん@お腹いっぱい。
12/04/03 20:44:46.90
>>725
まず入ってるであろうコマンドのことだよ
coreutils と読み替えてもらっても結構

727:名無しさん@お腹いっぱい。
12/04/03 20:46:12.15
この程度で揚げ足取ったつもりなのが笑える

728:名無しさん@お腹いっぱい。
12/04/03 20:52:43.65
つまりシェルビルトインコマンドは禁止ということですね

729:名無しさん@お腹いっぱい。
12/04/03 21:13:29.78
ls /tmp/unko > /dev/null 2>&1 && echo yes || echo no

730:名無しさん@お腹いっぱい。
12/04/03 21:18:54.77
>>723
< /tmp/unko 2> /dev/null && echo ある

731:名無しさん@お腹いっぱい。
12/04/03 22:18:53.41
(< /tmp/unko) 2> /dev/null && echo ある

732:名無しさん@お腹いっぱい。
12/04/04 10:03:23.15
testと[って同じだって書いてあるけど、]の立場はどうなるの?

733:名無しさん@お腹いっぱい。
12/04/04 10:04:50.22
>>732
] はコマンドじゃないから

734:名無しさん@お腹いっぱい。
12/04/04 10:07:01.64
] は [ の引数

735:名無しさん@お腹いっぱい。
12/04/04 10:52:50.01
testの引数にはならないの?

$ test -f /tmp/unko ]
-bash: test: /tmp/unko: binary operator expected
なんかエラーでた

736:名無しさん@お腹いっぱい。
12/04/04 10:54:52.95
自分が [ って名前かどうかで、 ] が最後にあるべきかどうか判断するんだよ

737:名無しさん@お腹いっぱい。
12/04/04 10:59:35.40
>>723
なんで [ じゃだめなの?

738:名無しさん@お腹いっぱい。
12/04/04 12:05:16.44
>>736
うぉぉ マジだ。 test.c ってこんなことやってんのか。
はぁー 無駄にすげぇーなー

739:名無しさん@お腹いっぱい。
12/04/04 12:15:50.42
20年遅れてるスレ行けよ。何でいまさら誰でも知ってる話題でこのスレ無駄使いしてるの?

740:名無しさん@お腹いっぱい。
12/04/04 12:21:38.54
test -e

741:名無しさん@お腹いっぱい。
12/04/04 12:40:51.61
>>740
test以外でかっこいい方法で

742:名無しさん@お腹いっぱい。
12/04/04 13:12:21.67
かっこいい(笑)

743:名無しさん@お腹いっぱい。
12/04/04 13:21:55.37
評価基準がよくわからん。

744:名無しさん@お腹いっぱい。
12/04/04 15:21:58.49
>>743
coolかどうかってことだよ

745:名無しさん@お腹いっぱい。
12/04/04 15:23:15.61
それがわからん。

746:名無しさん@お腹いっぱい。
12/04/04 15:43:57.60
>>739
お前2でなに言ってんだよ

747:名無しさん@お腹いっぱい。
12/04/04 16:47:37.67
>>746
どういう意味?

748:名無しさん@お腹いっぱい。
12/04/04 23:21:13.48
教えてください
TERM=$( (echo 'console() {
term="$2"; for i do
case $i in
term=*) term=$(expr "$i" : "term=¥(.*¥)")
esac
done; echo "$term"; exit 0
}'
というシェル関数なんですが、制御構文が良くわかりません。
for 変数 in 引数1 引数2 …
do
  処理
done
とはかけ離れてますし(変数も引数もない)、
case 変数 in
   パターン1) 処理;;
   パターン2) 処理;;
   パターン3 | パターン4) 処理;;
   *) 処理;;
esac
が混じってますし...
case文のどのパターンにも当てはまらない時の処理に「term=」がくっついてるし...
これってどういう風に解釈すれば良いんでしょうか?

749:名無しさん@お腹いっぱい。
12/04/04 23:30:30.61
set a b c
for i; do echo $i; done
とかやってみれ

750:名無しさん@お腹いっぱい。
12/04/04 23:31:20.38
for に in がない場合は位置パラメータ($1 $2 ...)を使う。
位置パラメータをiにセットしつつforループを回して、
$iが term=* のパターンにマッチしたとき、
そのなんたらの部分(*にマッチした部分)をexprで抜き出して
変数termにセットする。
位置パラメータ全周したらその時点の $term を出力。

というconsole関数。


751:名無しさん@お腹いっぱい。
12/04/05 12:29:39.61
教えてください><
以下のようなテキストファイルがあって、これを読み込んで下のような結果にするスクリプトを書きたいんですがいい方法が思いつきません;
地区、支店、名前が同じものは一番右にある数値を足しこんで出力すると言うものです。
awk のgetline を使えばどうにかなりそう・・・というイメージなんですが、どなたかご教授ください(泣

テキストファイル
----------------------------
A地区 〇支店 佐藤 5
A地区 〇支店 佐藤 9
B地区 □支店 伊東 3
B地区 □支店 木村 3
B地区 □支店 木村 5
C地区 △支店 青木 4
C地区 △支店 青木 4
C地区 △支店 野村 1
----------------------------

結果
----------------------------
A地区 〇支店 佐藤 14
B地区 □支店 伊東 3
B地区 □支店 木村 8
C地区 △支店 青木 8
C地区 △支店 野村 1
----------------------------

752:名無しさん@お腹いっぱい。
12/04/05 12:39:50.77
>>751
awkで、getlineを使わずに普通にできる。
ただし、数字は半角で書いてないと計算できない。

753:名無しさん@お腹いっぱい。
12/04/05 12:48:51.09
>>751
あっちスレの削除依頼出してきてよ。

754:名無しさん@お腹いっぱい。
12/04/05 13:03:00.03
>>753

すみません、やり方がわからないんで・・・
後で出します;

755:名無しさん@お腹いっぱい。
12/04/05 13:06:43.25
>>752

getline を使わずにですか・・・
ちょっとヒントいただけますか?

756:名無しさん@お腹いっぱい。
12/04/05 13:21:01.61
>>751
awk使わずにシェルだけでできるよ。
ただし、スペースは半角に、数字も半角にしてから実行すること。
標準入力から入力。


#!/bin/sh

p_district=
p_branch=
p_name=
n=0
while read district branch name val; do
if [ "$district" = "$p_district" ] &&
[ "$branch" = "$p_branch" ] &&
[ "$name" = "$p_name" ]; then
n=`expr "$n" + "$val"`
else
[ "$p_district" ] && echo "$p_district" "$p_branch" "$p_name" "$n"
p_district=$district
p_branch=$branch
p_name=$name
n=$val
fi
done
echo "$p_district" "$p_branch" "$p_name" "$n"

757:名無しさん@お腹いっぱい。
12/04/05 13:33:45.35
>>756

お~、有難うございます!大変助かります!
半角にして試して見ます。
ちなみに
$0 テキストファイル
といった具合に、テキストファイルを引数にして読み込み処理する、というようなことも出来るでしょうか?




758:名無しさん@お腹いっぱい。
12/04/05 13:35:37.33
>>757
引数にしたかったら、
>>756 のしたから2行目の done のところを done < "$1" に修正すれば良い。

あと、入力ファイルはあらかじめソートされてること

759:名無しさん@お腹いっぱい。
12/04/05 13:42:26.55
>>758

すごい!
自分もこんなにあっさりスクリプトが書けるようになりたいものです・・・
758 さん、有難うございました、大変勉強になりました。

760:名無しさん@お腹いっぱい。
12/04/05 13:50:38.48
awkなんてAhoでもできることなのに

761:名無しさん@お腹いっぱい。
12/04/05 14:44:15.71
だれか>>760の座布団全部取り上げろ

762:名無しさん@お腹いっぱい。
12/04/07 17:42:25.29
ディレクトリのmvできるかどうかを事前にチェックしたい

特定のディレクトリ以下に アクセス不能とか移動不能なものが
あるかどうかを調べたいんですが、findでいいですかね

763:名無しさん@お腹いっぱい。
12/04/07 19:40:38.64
だめだ、難しい
グループでOKになってるときのパターンがネックだ
これのせいでワンライナーにならん

764:名無しさん@お腹いっぱい。
12/04/07 22:52:59.06
>>762
find . ! -readable | wc -l
でダメ?

765:sage
12/04/10 19:58:25.17
for i in {1..10}; do command 1> ${i}.txt 2> ${i}.log &; done

とかやると,
[1] + suspended (tty output) ...
とかなって処理が終了しない.なぜぇ・・・


766:名無しさん@お腹いっぱい。
12/04/10 21:04:40.05
それはね…

767:名無しさん@お腹いっぱい。
12/04/11 08:00:04.70
>>765
面白いと思う

768:名無しさん@お腹いっぱい。
12/04/12 09:02:11.67
;が邪魔だって文句いわれたから、
はずして実行したら {1..10}.txt とかできたぞ
どうしてくれる

マジレスすると、commandの中身なによ

769:sage
12/04/12 10:33:02.93
Cで書いたプログラムだね.

770:名無しさん@お腹いっぱい。
12/04/12 19:19:17.01
commandはシェルビルトインコマンドでしょ

771:名無しさん@お腹いっぱい。
12/04/12 19:30:36.07
というか、>>765 実行してもそういう現象は起きないので、
回答欲しかったらもっと具体的に "how to repeat" 書いてくれ

772:名無しさん@お腹いっぱい。
12/04/12 21:09:49.38
>>765
そのcommandのプログラムがSIGTTOUをSIG_DFLに戻してしまってるんだろ。
普通ならシェル側でSIGTTOUはSIG_IGNにするからsuspendはしないようになってる。

773:名無しさん@お腹いっぱい。
12/04/12 21:25:50.42
>>771
Steps to Reproduce だろ

774:名無しさん@お腹いっぱい。
12/04/12 21:34:14.02
>>773
How to repeatで合ってる。というか、そんなところに突っ込んでも面白くない。

775:名無しさん@お腹いっぱい。
12/04/12 22:19:43.60
再現性の話ならreproduceがふつー


776:名無しさん@お腹いっぱい。
12/04/12 22:24:50.96
SIGTTOUについて答えられない奴が持論の英語を主張して話題逸そうとしてるなw

777:名無しさん@お腹いっぱい。
12/04/12 22:27:19.83
「バグの出し方」と書かれてる文章に、
「バグの再現手順」だろ? と突っ込んでるようなモン。

778:名無しさん@お腹いっぱい。
12/04/12 23:01:56.84
GNUのバグトラッキングシステムがHow-To-Repeatってフィールド使ってるね
URLリンク(www.gnu.org)

779:名無しさん@お腹いっぱい。
12/04/13 06:11:12.98
>>765
エスパーするとzshの最近のバージョンでのバグ。

780:名無しさん@お腹いっぱい。
12/04/13 14:26:30.54
w3m &
で起きる奴とおんなじ.どうすればいいんだろ・・

781:名無しさん@お腹いっぱい。
12/04/13 14:34:14.58
何のこと?

782:名無しさん@お腹いっぱい。
12/04/13 14:44:26.87
>>781

>>768の件.

783:名無しさん@お腹いっぱい。
12/04/13 14:44:40.34
>>780
set +m
で、ジョブコントロールを無効にすれば桶。
ただ、シェルスクリプト中から起動すればデフォで set +m 状態なんだがな。
コマンドラインから直接起動してるのか。

784:名無しさん@お腹いっぱい。
12/04/14 21:01:39.51
どこに書いていいのかわかんないから、ここに書いてみる。
shell script書いててはまったんだけど、
 ls -l /etc | sort -k4 -n
がファイルサイズでソートしてくんない。
こんな↓感じで、なんか部分的にしかソートしてくれないみたい。
URLリンク(dpaste.org)

バグ?
理由を知ってる人がいたら教えてちょうだい。

環境: debian squeeze
$ uname -a
Linux bauhaus 3.2.0-2-rt-686-pae #1 SMP PREEMPT RT Fri Apr 13 02:23:30 JST 2012 i686 GNU/Linux
$ sort --version
sort (GNU coreutils) 8.5

785:名無しさん@お腹いっぱい。
12/04/14 21:09:58.78
>>784

sort -k5 -n だろ

786:名無しさん@お腹いっぱい。
12/04/14 21:10:24.24
まぁ、ls -Sで良いんじゃないのか

787:名無しさん@お腹いっぱい。
12/04/14 21:15:57.76
>>784
> 理由を知ってる人がいたら教えてちょうだい。
使い方が間違っている。

788:名無しさん@お腹いっぱい。
12/04/14 21:18:22.79
0番目から数えたくなる気持は分からなくもない

789:名無しさん@お腹いっぱい。
12/04/14 21:26:12.51
いや、だって、man sort したら、
-k POS1[,POS2]
-K POS1[,POS2] ソートフィールド指定の POSIX 形式。今後はこちらが
推奨される。行の POS1 から POS2 までのフィールドを指定する。
POS2 を含む。 POS2 が省略されたら行末まで。 フィールドと文字位置
はそれぞれ 0 から数えはじめる。
て書いてあったんだもん。
それを何も考えず信じたのでした。

LANG=C man sort だと、
-k, --key=POS1[,POS2]
start a key at POS1 (origin 1), end it at POS2 (default end of line)
てなってるのね。
確かに -k5ならソートしてくれたよ。

なんだかスレ汚し失礼しました。

790:名無しさん@お腹いっぱい。
12/04/14 21:34:49.42
本当だ。普段manpageは英語のものしか見ないから気付かなかった。

791:名無しさん@お腹いっぱい。
12/04/15 01:03:11.15
俺もだまされた。
さすが Linux とおもた。

792:名無しさん@お腹いっぱい。
12/04/15 01:13:16.43
Linuxの日本語manはまったく整備されてないからなぁ

793:名無しさん@お腹いっぱい。
12/04/15 01:18:04.06
alias man='LANG=C man'
しとくのオススメ

794:名無しさん@お腹いっぱい。
12/04/15 01:20:40.59
$ man sort じゃなくて $ info sort がオヌヌメ

795:名無しさん@お腹いっぱい。
12/04/15 02:33:57.03
Linuxの日本語 manと言えば、最近 bash 4.2の manが
翻訳されたのが嬉しかった。

GNU bash 4.2 の翻訳
URLリンク(linuxjm.sourceforge.jp)

796:名無しさん@お腹いっぱい。
12/04/15 11:22:51.82
コマンド foo と同名の関数 foo を作成し、後者の中から前者を呼び出そうと思っています。
function foo {
 foo
}
しかし当然ながら無限ループになります。
解決策としては
function foo {
 `which foo`
}
という方法があります。
しかし毎回 which コマンドを起動するのがちょっと気にかかります。
別の方法として
function foo {
 ¥foo
}
というのを試しましたが、だめでした。¥foo はエイリアスには効くけど関数にはききませんでした。
というわけで、今のところ which コマンドを使う方法しかなさそうですが、もっといい方法があれば教えて下さい。

797:名無しさん@お腹いっぱい。
12/04/15 11:26:42.70
>>796
function foo {
 command foo
}

そのための「command」コマンド。

798:名無しさん@お腹いっぱい。
12/04/15 12:24:24.87
話は変わるけど、bashには`help'という組み込み関数があって、

bash$ help function

とか

bash$ help command

とかするとその部分の説明文だけ表示してくれる

799:名無しさん@お腹いっぱい。
12/04/15 13:24:53.76
単に
/usr/bin/foo
とかすればいいんじゃないの?

800:名無しさん@お腹いっぱい。
12/04/15 13:34:57.91
>>799
最適解(>>797)が既に出てるのに、外した回答するオマエは黙ってろ。

PATHが違ったら適応できないだろw

801:名無しさん@お腹いっぱい。
12/04/15 16:01:28.21
>>799のレスは別に問題視するようなものじゃない。
~の方が良いと書いてあれば別だが。

802:名無しさん@お腹いっぱい。
12/04/15 16:16:51.47
>>801
>>796 の質問で、わざわざ `which foo` と書いてることから、
絶対PATHで書いたのでは問題の解決にならないことは読みとれる。
質問者自信も絶対PATHを使う方法は知っている(けどそれじゃ駄目)と読みとれる。

質問の回答になってないのだから問題視されてもしょうがない。

803:名無しさん@お腹いっぱい。
12/04/16 01:51:19.72
>>801
>>799みたいなトンチンカンな回答にも丁寧に答えてあげている
>>800の優しさに気づけ

804:名無しさん@お腹いっぱい。
12/04/17 15:40:51.44
>>797
「command」なんて初めて知りました。完璧です。ありがとうございました。

>>802
状況としてはまったくそのとおりで、すばらしいエスパーっぷりですが、
799はそこまで敵視されるようなことを書いてるわけじゃないので、
そんなに怖がらせなくてもいいかなと思いました。
技術者同士はみんな仲良くね!戦うべき相手は別にいるよ!

805:名無しさん@お腹いっぱい。
12/04/17 16:49:46.48
>>800は常駐さんのお決まりレスです。
彼なりにイカしたレスだとお考えになっているのでしょう。
しばらくここにいれば慣れます。

806:名無しさん
12/04/23 01:47:23.08
検索コンプレックス

807:名無しさん@お腹いっぱい。
12/04/28 14:15:07.91
関数もexportできるようにならないかなぁ
環境変数ならぬ環境関数みたいな
便利だと思うんだけど

808:名無しさん@お腹いっぱい。
12/04/28 14:19:23.03
>>807
え? できるけど。

export -f

809:名無しさん@お腹いっぱい。
12/04/29 08:45:26.54
>>808
bash乙

810:名無しさん@お腹いっぱい。
12/04/29 09:44:51.95
      ____
     /      \
   /  _ノ  ヽ、_  \
  /  o゚⌒   ⌒゚o  \   不毛な言い争いがまた始まるお…
  |     (__人__)    |
  \     ` ⌒´     /


811:名無しさん@お腹いっぱい。
12/04/29 10:46:16.86
キミの好物じゃないの

812:名無しさん@お腹いっぱい。
12/04/29 17:13:31.08
>>808
ほんとだ、bashだとexport -fでできるのね
zshだと駄目なんだけどオプションが違うんだろうか

813:名無しさん@お腹いっぱい。
12/04/29 17:16:47.95
zshは今誰も使ってないからバグが放置されてるんじゃないか?

814:名無しさん@お腹いっぱい。
12/04/29 18:14:30.17
>>813
そうなんだぁ・・・
いっそbashに戻ろうかな

815:名無しさん@お腹いっぱい。
12/05/06 03:50:24.36

質問です。

複数のコマンドの実行結果をソートしたいですが、うまくいきません。例えば、
イメージ的には以下のような感じ。

{
cat FILE_A
find PATH1 -print
find PATH2 -print
find PATH3 -print
} | sort > FILE_A

以下を試しました

find PATH1 -print >> FILE_A
find PATH2 -print >> FILE_A
find PATH3 -print >> FILE_A

cat FILE_A | sort > FILE_A

こうすると最後の FILE_A のファイルに結果がすべて出力されず尻切れになり
ます。


816:名無しさん@お腹いっぱい。
12/05/06 03:59:02.05
zshかbash系だとして一行で済ますなら
$ cat <(find PATH1) <(find PATH2) <(find PATH3) | sort

$ cat < FILE_A | sort > FILE_A
が失敗するのはまあそんなものだと思っておけばいい。
同じファイルから読み込んで出力するのは失敗する。

$ cat < FILE_A | sort > FILE_B
ならおk

817:名無しさん@お腹いっぱい。
12/05/06 04:09:18.13
(rm FILE_A; sort > FILE_A) < FILE_A
みたいな手もあるが、間違えたら泣ける。


818:名無しさん@お腹いっぱい。
12/05/06 04:15:04.88
同じ条件で検索するなら
find PATH1 PATH2 PATH3 | sort
でいいよな。

819:名無しさん@お腹いっぱい。
12/05/06 05:15:17.42
>>815
> cat FILE_A | sort > FILE_A
マルチタスクな OS では普通パイプやリダイレクトの際に前後の
プロセスが同時に起動する。
ファイルを読むプロセスが終了するのを待ってファイルを書くプ
ロセスが起動する訳ではない。

なので、上記の場合は最後に書き込むファイル名を変更しなければならない。

820:名無しさん@お腹いっぱい。
12/05/06 14:36:51.94
TEMP=`tempfile`
cat FILE_A > "$TEMP"
find PATH1 -print >> "$TEMP"
find PATH2 -print >> "$TEMP"
find PATH3 -print >> "$TEMP"
sort "$TEMP" > FILE_A


821:名無しさん@お腹いっぱい。
12/05/06 14:53:36.25
すみませんが添付ファイルは梨の奉公でお願いします

822:名無しさん@お腹いっぱい。
12/05/06 15:27:35.80
>>815
URLリンク(www.gnu.org)
cat FILE_A | sort -o FILE_A


823:名無しさん@お腹いっぱい。
12/05/06 16:20:24.14
>>822
catとパイプが無駄です。

sort -o FILE_A FILE_A

824:名無しさん@お腹いっぱい。
12/05/06 17:20:10.08
ランダルシュワルツの不要なcat添削を思いだした

825:名無しさん@お腹いっぱい。
12/05/06 18:55:31.70
cat議論はこのスレの>>147-213あたりで延々やってるな。

826:名無しさん@お腹いっぱい。
12/05/06 19:22:02.88
添付ファイルを使わないのは大手SIerじゃ常識だね。

827:名無しさん@お腹いっぱい。
12/05/06 19:23:49.29
思案パイプ

828:名無しさん@お腹いっぱい。
12/05/07 19:19:08.78
対話方式にならないようにシェルスクリプト自信がroot権限で実行されるようにするスクリプトって作れますか?

829:名無しさん@お腹いっぱい。
12/05/07 21:03:44.73
>>828
対話的コマンドでもexpectでなんとかなる

830:名無しさん@お腹いっぱい。
12/05/07 21:11:42.22
>>829
そういう意味じゃなくて、シェルスクリプト中で su -c hoge とかしないで
root権限の動作をさせたいという質問かとエスパー。

831:名無しさん@お腹いっぱい。
12/05/07 21:16:30.15
基本的にsuidはシェルスクリプトでは許可されてないからねえ。
昔あったsuidperlみたいなののbash版を探してみたけどないみたいだし。
sudersに対象となるスクリプトに対してNOPASSWDを設定するぐらいしか思いつかないや。


832:名無しさん@お腹いっぱい。
12/05/08 02:00:49.38
>>828
できます
コマンドラインを実行するだけのプログラムを作って
setuidするば

833:名無しさん@お腹いっぱい。
12/05/08 07:52:21.31
>>832
>>831

834:名無しさん@お腹いっぱい。
12/05/09 13:22:49.97
URLリンク(forum.xda-developers.com)
ここに書いてあるシェルスクリプトを動かしてみたんですが、
Syntax error: "do" unexpectedと返されてしまいます
ヒントだけでもいいんで教えてください。



835:名無しさん@お腹いっぱい。
12/05/09 13:28:11.27
-x 付けて実行してどこでエラーか見てみたら
bash -x secrets.sh

836:名無しさん@お腹いっぱい。
12/05/09 13:29:47.52
>>835
わからないなら黙ってろ

837:835
12/05/09 13:30:45.77
あ、スレ間違えてたorz

838:名無しさん@お腹いっぱい。
12/05/09 15:17:41.55
なぜかしら、回答としては合ってる気がするぞw

839:名無しさん@お腹いっぱい。
12/05/10 06:54:48.81
コピペの際に文の末尾に\rが入っちゃってるとか。

840:名無しさん@お腹いっぱい。
12/05/14 22:36:21.02
alias cd=chdir
function chdir {
if [ -r "$1" -a -d "$1" -o "$1" = "" ] ; then
local i
for i in 8 7 6 5 4 3 2 1 0 ; do
dirstack[$i+1]=${dirstack[$i]}
done
dirstack[0]=`pwd`
\cd $1
fi
pwd
}
function ds {
echo "p:"`pwd`
local i
for i in 0 1 2 3 4 5 6 7 8 9 ; do
echo "$i:${dirstack[$i]}"
done
}
bash用のをcsh(tcshですが)に書き換えてもらえないでしょうか。


次ページ
最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch