1 名前:シェルスクリプトライター mailto:sage [2011/12/10(土) 20:06:40.38 ] シェルスクリプトの総合スレです。 スクリプトのお勉強・自慢・腕試しなどにどうぞ。 □お約束 ・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。 Linuxユーザは/bin/shの正体がbashなので特に注意。 FreeBSDユーザは/bin/shの正体がashなので注意。 v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。 src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/sh/ heirloom.sourceforge.net/sh.html ・csh/tcshのシェルスクリプトは推奨されません。 (理由は「csh-whynot」でググれ) ・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。 manや参考リンクを見ましょう。 aproposないしはman -kでそれらしい単語による簡単な検索もできます。 ・シェルスクリプトのことをシェルってゆーな ・シェルで使えるワイルドカード等は正規表現ではありません。 正規表現の話題はスレ違い(正規表現スレへ) □初心者へのアドバイス: ・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも RubyやPerlの方が適した仕事には素直にそちらを使いましょう。 ・知らないコマンドが出てきたらmanを引きましょう。 ・思い通りに動かないときは、まずは sh -x でトレースしましょう。 前スレ シェルスクリプト総合 その18 hibari.2ch.net/test/read.cgi/unix/1308195527/ 次スレは >>970 で。
552 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 12:19:43.22 ] あらkshからbashになったのね。> Oracle Solaris 11の/bin/sh
553 名前:526 mailto:sage [2012/03/16(金) 12:23:58.00 ] 私の為に争わないでください 課題の回答だけお願いします
554 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 12:24:33.25 ] >>552 えっと……どこをどう読めばそうなるのかとても不思議
555 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 14:29:31.51 ] >>553 ちったぁ自分で考えろ
556 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/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 mailto:sage [2012/03/16(金) 14:45:06.16 ] 時間が無い。早くしてください。 来週の月曜の朝10時までにお願いします。 過程とか不要です。答えだけ書いてください。 もし回答以外のことも書きたい場合はスクリプトを*で囲って 目立つようにしてください 書き方の例を示します **************************** a = 3 x + y = 5 ****************************
558 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 14:46:05.73 ] 今それどころじゃないからちょっと黙ってて。
559 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 14:51:59.23 ] ここまで、 「宿題は自分でやれ」 「来年はちゃんと講義聞こうな」 なし
560 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 15:38:56.29 ] 分からない人は黙っててください
561 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 18:41:04.43 ] >>560 それって、お前も黙らなきゃいけないんじゃないか?
562 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 18:44:07.77 ] すべて分かった上で言ってるんだよ。
563 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/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 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 18:47:50.70 ] >>563 だからぁ、bashじゃ駄目だっておっしゃってますが・・
565 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 21:19:30.14 ] >>548 > $((expression))がサポートされてなければexprに書き換えれば > すむ事だから大した問題じゃないよね。 letは使えないの?
566 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 21:21:16.68 ] もうできてる人が何人もいるんです 3/19の10:00まで待つと書きましたが、前倒して3/17の16:30までとします >>557 にあるフォーマットでお願いします
567 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 21:22:56.00 ] >>565 もちろんletも使えない。
568 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 21:41:50.80 ] >>563 最大公約数求めるのに引数デクリメントしながらすべて割って試すとか 総当たりの非効率アルゴリズム使ってボケるんなら、 最小公倍数でもインクリメントしながら順番に割って総当たりするアルゴリズムで ボケるべき。
569 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 21:49:10.39 ] つか, /bin/sh って言ってる奴いるけど, どの時点でどの機能が入った /bin/sh まで許せるんだ? FreeBSD の ports で拡張機能すべて許可した v7sh では func(){} すら Syntax error なんだが... # 少なくとも ``#!/usr/bin/env bash'' くらいにしないと販促だ >>563
570 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 21:54:56.85 ] >>566 バカ共の相手が面倒になったので締め切りました。 やっぱりバカしか居ないんだな。
571 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 22:25:57.27 ] なりすまし多いね
572 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/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 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 22:28:07.31 ] 自演も多いよ
574 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 23:17:57.60 ] 本人です 3/17 17:00までに提出しないと単位が足りなくなるのが分かったので質問してます レポートに貼り付けるのは私がしますので、3/17の16:30までにお願いします また他の皆さんについても、ソースにバグがないかどうか、早急なチェックとデバッグを 期待しています >>557 にあるフォーマットでお願いします
575 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 23:25:20.31 ] そろそろ飽きたわ。もう十分釣れただろ
576 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 23:37:15.49 ] ていうかもうできてんじゃないの?確かめてないけど
577 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 23:39:45.15 ] 編集前ディレクトリと編集後ディレクトリを比較して、 変更がないファイルを編集後ディレクトリから削除する シェルスクリプトを書こうとしています。 diffをディレクトリ同士で実行し同名ファイルを探し その同名ファイルをdiffし返値が空なら削除という操作を 再帰的に階層を掘って実行すれば良いと思うのですが、 どうも何から書けばいいのか詰まってしまいました。 奇特な方居ましたらアドバイスお願いします。
578 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/16(金) 23:45:20.44 ] >>577 まず、man diffをちゃんと嫁
579 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/17(土) 00:14:42.67 ] >>578 オプションよく読んでいませんでした。 読んで出直してきます。ありがとうございました。
580 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/17(土) 05:25:42.88 ] >>577 目的に対する作業の方法が間違ってる気がする。 何のために「編集前ディレクトリと編集後ディレクトリを比較して、 変更がないファイルを編集後ディレクトリから削除する」のか を書いた方が、適切な答えが帰ってくると思う。
581 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/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 mailto:sage [2012/03/17(土) 07:30:38.91 ] >>572 さんありがとうございます。/bin/sh命令のみですね。 これで提出します。
583 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/17(土) 15:36:57.64 ] >>572 こんなバカみたいな総当たりはダメだって言われちゃいました もっと数学的な解法をアルゴリズム化したものでないとダメです 結果が正しければいいってレベルじゃないんです 100万とか1000万とか、それ位大きな値になると、ちっとも終わらないじゃないですか 期限は今日の16:40までとします くれぐれもよろしくお願いします
584 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/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 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/17(土) 22:26:32.20 ] >>577 LANG=C diff -qrs a b の出力結果でなんとかする というかバージョン管理システムを使うのが良い気がする
586 名前:名無しさん@お腹いっぱい。 mailto:sega [2012/03/19(月) 12:31:35.64 ] A=*.txt B=$A touch $B とすると、"*.txt"というファイルが出来てしまうんですが これ$Bを展開させたいときはどうすればいいんですかね
587 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/19(月) 12:40:39.27 ] >>586 本当に >>586 のとおりに実行したのなら *.txt は展開される。 展開されないのはカレントディレクトリに *.txt にマッチするファイルがないから。 すでにファイルがなければ展開しようがない。
588 名前:586 mailto:sage [2012/03/19(月) 12:56:05.81 ] >>587 ヒントありがとうございます oppai.txt がある場合⇒ oppai.txtにタッチ oppai.txt がない場合⇒ *.txt を作成 という動きになりました まーこれはこれで使い物になりませんわ
589 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/19(月) 13:11:29.40 ] 存在をチェックしてからtouchすればいいじゃない。
590 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/19(月) 13:13:49.05 ] >>588 もし「存在しなければ作成したくない」という意図なら、 touch -c $B で桶。
591 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/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 mailto:sage [2012/03/19(月) 14:20:52.93 ] >>590 天才や・・・ UNIX板には天才がたくさんいる みんなありがとう
593 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/19(月) 14:28:02.20 ] いや、みんなは普通だよ。
594 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/19(月) 15:43:16.30 ] >>591 のアホさが光るな。
595 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/19(月) 15:45:13.28 ] >>586 これなんでBをはさんでるの?
596 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/19(月) 17:56:07.30 ] おそらく A=*.txt で *が展開されなかったから Bに代入し直せば再解釈されて展開されると勘違いしたのだろう
597 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/19(月) 19:53:24.01 ] 結局、どこで展開されたんだろうね
598 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/19(月) 19:56:34.87 ] ん? A=*.txt でも B=$A でも 変数直接代入時は展開されないよ。 touch $B みたいにクォートなしで参照した時に初めて展開される。
599 名前:586 mailto:sage [2012/03/19(月) 19:58:57.99 ] >>598 ありがとう。それだけが心残りだったんだ
600 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/19(月) 20:04:56.95 ] shを作ったBourneは天才だね。
601 名前:名無しさん@お腹いっぱい。 [2012/03/19(月) 20:08:20.98 ] あのソースコードは勘弁して欲しい。
602 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/19(月) 21:12:40.16 ] ソース読んだのか あんたスゲーや
603 名前:名無しさん@お腹いっぱい。 [2012/03/19(月) 22:06:26.63 ] ソースコードつーか、これな。 ttp://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mac.h
604 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/20(火) 08:01:57.14 ] x68000.q-e-d.net/~68user/unix/pickup?keyword=test&target=command のサイトに、 #!/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 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/20(火) 09:04:17.23 ] > [ ! = 'q' ] これはそのように解釈するtestもあるから注意しろ。くらいでいいと思う。 > どのような解釈をすると、!cがtest cd /etcに置換されるのでしょうか? ヒストリ置換だろ。
606 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/20(火) 17:36:56.09 ] >>605 今の時代、そのエラーが出るshを使っている人、いるのかね?
607 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/20(火) 17:41:15.64 ] 今の時代、 [ ! = ! ] [ [ = [ ] [ ] = ] ] [ = = = ] [ -f = -f ] など、すべて文字列の比較として期待通りに動作する
608 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/20(火) 17:51:22.47 ] しかし未だに [ x"$hoge" = x"yes" ] などと書いてる人を見掛けるな #!/bin/bashとか書いてるのに
609 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/20(火) 19:57:58.15 ] スクリプトインジェクション対応だよ
610 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/20(火) 21:45:56.60 ] [ "$hoge" = yes ] だとして具体的にどうインジェクトするんだよ
611 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/20(火) 23:34:08.60 ] >>610
612 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 09:04:25.40 ] >>611 どうインジェクションするか解説お願いします
613 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 10:08:32.37 ] hoge=']; /bin/sh;'
614 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 10:47:17.62 ] ってゆーか、こういう場合は case "$hoge" in yes) ...;; esac って書くよね、ふつー。[Yy][Ee][Ss] なんかに変えるのも簡単だし。
615 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 11:14:27.91 ] >>613 >>610 はダブルクオートで囲ってるから、[コマンドの第一引数として$hogeの中身が渡るんで、そのhogeの値はそのまま[コマンドが解釈する。 どうあがいてもインジェクションなんて無理だと思うんだが。
616 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 11:26:14.79 ] てきとーに言ったんだろ。 もうカンベンしてやれ。
617 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 12:19:06.39 ] 本人乙
618 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 13:26:55.78 ] 違うよ。
619 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 13:38:09.35 ] 最近のJavaScriptのようにeval使いまくりで威張る奴か。
620 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 14:28:05.05 ] >>619 座布団
621 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 15:37:01.15 ] 全部持ってって〜
622 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 19:24:26.73 ] >>606 $ busybox ash $ hoge=! $ if [ "$hoge" = 'q' ]; then echo QUIT; fi ash: q: unknown operand
623 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 22:56:44.16 ] https://uec.usp-lab.com/SHELL_TIPS/CGI/SHELL_TIPS.CGI?POMPA=TIPS_not_while に >シェルスクリプトに制御構文が増えることを極力避けるように様々な工夫をしている。 >制御構文を避ける理由はコードが読みにくくなるためだ。 >これまで制御構文whileやforのはずし方について書いてきた。 >処理速度を高速化するためにwhileやforをコマンドに置き換えるというのは、 >それなりの効果が期待できる方法だ。 >シェルスクリプトに制御構文であるforやwhileが出てきたら、 >何か避ける方法がないか探してみるとより高速なスクリプトが書けるようになるかもしれない。 ってかいてあって、いろんな例が書いてあったり、 変なパッケージ(python製)を入れて、そのコマンドを使ったりしてるんですね。 僕は制御構文外すと逆に可読性がおちたり、 pythonで書かれたコマンドを呼び出すより、シェルスクリプトで制御構文書いた方が 早いと思うんですけど、おかしいですかね?
624 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/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 名前:名無しさん@お腹いっぱい。 [2012/03/21(水) 23:09:05.42 ] お前はマニュアル読むという事を考えたことが無いのか?
626 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 23:34:20.22 ] >>624 うん、sedの超基本的な使い方で出来る
627 名前:名無しさん@お腹いっぱい。 [2012/03/21(水) 23:34:53.13 ] sedを使えばいいと思うよ
628 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/21(水) 23:41:30.82 ] >>623 そのページを見て思ったことは、xargsは便利だね、くらい
629 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/22(木) 00:58:20.98 ] >>623 シェルスクリプトに限らず、プログラム書く時に(一部の)制御構文を使わないってのは個人的に良くやる。効率とか性能とか抜きで。 ゲームの縛りプレイみたいなもんだけど、意外なテクニックを発見したりできて楽しめるよ。おすすめ。 上司や同僚に見つかったら>>623 のサイトみたいな適当なウンチクで誤魔化せばOK。
630 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/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 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/22(木) 02:23:18.01 ] >>629 BASICのころはあったけどな。 if文分岐とかで速度差が出ないようにするとかで。 今はそういうのする必要ないけど。
632 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/22(木) 08:22:33.32 ] PerlやC#、COBOL、Fortran、アセンブリなんかも、見慣れてなければ読みにくく 感じるものさ
633 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/22(木) 08:28:41.72 ] Whitespaceもな。
634 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/22(木) 09:18:49.18 ] 俺はsedが嫌いなので、できるだけperlを使うようにしている
635 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/22(木) 09:56:14.04 ] それは報告しなくてもいいです。
636 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/22(木) 11:24:16.01 ] kshで待ち行列を作りたいんですが、どうしたらいいでしょう? 基本動作はキューなんですが、 1 2 3 ↓1を実行 2 3 1 2 3 ↓2を実行 1 3 としたいです unset 配列[N]でインデックスを詰めてくれればこんなの楽勝なのに…
637 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/22(木) 11:37:02.12 ] >>636 ファイルにしたらいい
638 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/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 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/22(木) 20:22:13.25 ] >>636 unset array[N] で要素をunsetした後に、 array=(${array[@]}) でセットしなおせばインデックスは詰まる。 >>638 とは違って位置パラメータを壊さずに済む。
640 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/22(木) 21:29:35.34 ] >>639 かっこういい
641 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/23(金) 22:05:53.20 ] シェルスクリプト学び始めたばかりの初心者です。 ・ファイルを指定フォルダ内へコピー ・同名ファイルが存在する場合は、 既に存在するファイル名を「ファイル名 (1)」へ変更し、 既に「ファイル名 (1)」が存在しているのであれば、 それをさらに「ファイル名 (2)」へ変更し、、、(繰り返し) というシェルスクリプトを書きたいんですが、 既に「ファイル名 (*)」が存在する場合に*の数字を どのようにすれば知ることができますか? *さえ知れたらexprを使えば出来るとは思うのですが... アドバイスお願いします。
642 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/23(金) 22:27:01.94 ] >>641 逆に考える。 変数iとかに1を入れておいて、 "ファイル名($i)" が存在したら iをインクリメントして "ファイル名($i)" にリネームする。
643 名前:名無しさん@お腹いっぱい。 [2012/03/23(金) 22:28:54.51 ] 再帰使わないとややこしいことになりそうだな。
644 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/23(金) 22:32:05.36 ] 最小の空きを使うんでいいの? i=1; while [ -f "file($i).txt" ]; do i=`expr $i + 1`; done; echo $i
645 名前:名無しさん@お腹いっぱい。 [2012/03/23(金) 22:52:22.20 ] 「それを」が何を指すかによる。
646 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/23(金) 22:56:33.59 ] GNU cp なら --backup=numbered とか?
647 名前:名無しさん@お腹いっぱい。 [2012/03/24(土) 01:18:46.16 ] なんか見覚えがある処理だと思ったが logrotate かいな。
648 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/24(土) 10:30:46.53 ] >>641 つまりアヌスを知りたいと……教えてあげよう
649 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/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 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/03/24(土) 18:40:54.37 ] 突っ込みどころ多いな
651 名前:名無しさん@お腹いっぱい。 mailto:sage [2012/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 mailto:sage [2012/03/24(土) 21:11:20.76 ] 皆さんアドバイスありがとうございました。 642さんの意見を参考に書いていたら、 651さんとほぼ同じようなものが書けました。 勉強になりました!