シェラーの皆さんこんにちは。 今日も元気にワンタイマーしてますか?
>>2 マジ質問ですいません。ワンタイマーって何ですか?
4 :
名無しさん@お腹いっぱい。 :2011/12/10(土) 23:18:47.00
ワンライナーかな、とも思ったがシェルでワンライナーはそれほど重視されないしな…
相手すんなよ。
1000 :名無しさん@お腹いっぱい。 :sage :2011/12/11(日) 16:41:38.19 -z って変数が空か入ってるかぢゃ無いのかよ
>>6 変数が未設定か設定済みかをテストしたい時は、
test -z "${var+X}"
を使う。varに空文字列がセットされていても「設定済み」と判定する。
なるほどぉ。ためになるなぁ。 でもさ、スクリプトの場合あらかじめunsetで初期化しない? unsetを初期化と呼ぶのかどうかさえ知らんのだけど……。
9 :
名無しさん@お腹いっぱい。 :2011/12/13(火) 15:30:20.06
冷やすとリングはワンタイマーだよね?
10 :
名無しさん@お腹いっぱい。 :2011/12/13(火) 17:16:35.40
here string は PowerShell用語だったという記憶。
bashのmanにも記載はあるが、何処のどいつが言い出したのかは分からんね 辿っていけば時期は分かるだろうが、PowerShellに関しては全く知らん
12 :
名無しさん@お腹いっぱい。 :2011/12/13(火) 20:54:11.16
bashのhere string... へー << じゃなくて <<< を使うんだな。 $ cat <<<XXX XXX
つまりドザか
Powershellより昔の用語じゃないか? ヒアストリングっていまいち使いどころがわからんけど。
ブロックコメントアウトには常用するよ #!bash :<<'#COMMENT' echo $PATH #COMMENT
16 :
名無しさん@お腹いっぱい。 :2011/12/19(月) 00:05:06.81
それはhere stringじゃなくてhere documentじゃねーの?
ごめん、ヒアストか。たしかに使いどころがないというか、これくらいしか用例知らない。 awk <<< "$*" '{ for (i = 1; i <= NF; i++) { print $i } }'
>>15 それはシェル内部で添付ファイル作られるから動作が無駄だな
19 :
名無しさん@お腹いっぱい。 :2011/12/19(月) 08:25:18.78
grep -q 'pattern' <<< 'string' とか使えると思うけど
>>18 その添付ファイル名を知る方法ってない?
終了時に自動で美しく消されるなら使い捨てのawkやsedを埋め込むのに使いたい。
mktempとか面倒だし本題からずれて見難いしさ。
>>20 exec 3<< EOF
hoge
EOF
cat /dev/fd/3
とか?
「無駄だな」マンw
シェルスクリプトライターなら、ソースで語れよ 無駄無駄だけじゃ、何も進まないぜ(キリッ
>>15 については、コメントアウトのつもりでも
実際には内部でtmpファイルが作られるという動作が実行され、
コメントになっていない、ということを
>>18 が言ってるんだろ?
単に書き方が無駄だということじゃなくて、
根本的にコメントになっていないということ。
csh, commdnd.comでさえgotoがあるのにね。 cshの非実行部は構文解析されるんだっけ?
eucのサーバにおいて、sjisのファイルをcatすると文字化けするのですが、 対処方法としてはどうすればいいでしょうか?
nkf -e
iconvはエラーで中途終了しちゃうからnkfの方が推奨。 (まあ、-sもあるとは言え)
半角文字とか記号とかが混じったデータだと、iconvじゃ変換できないってことがあった 日本語ならnkfの方がまだ分があるって気がする
sjisじゃなくてcp932でもそうなるならiconvのバグ臭いが
>>30 -c オプションでも解決はしないので nkfお勧め
-cのないiconvもあるよな…cygwinだっけか…(死亡フラグ
そもそもcygwinじゃデフォルトで入らないしnkfのパッケージもないから 入れてたpythonでフィルタ書いて使ってる
初歩的な質問なのですが、
>>26 の「eucのサーバ」ってどういう意味ですか?
サーバーの設定で文字コードって指定できるんですか?
サーバーのロケール設定が euc ってことじゃね?
別に i18n で euc を指定していようと、Terminal で sjis を指定してれば 文字化けだけは防げると思うよ。 文字化けだけは。
>>35 make一発でコンパイルできるやん
# Makefileにinstall targetがないけどw
iconvは自動判別してくれないよね?
43 :
名無しさん@お腹いっぱい。 :2011/12/26(月) 01:28:47.74
後で使うなら別だけど、 いちいち変数に入れずに、そのままアウトプットしちゃえばいいんじゃないの?
>>43 > #! /bin/bash
出直しな。
そういえばむかし圧縮形式ごとのオプションが面倒で全部kaitoってスクリプトにしてカレントにディレクトリつくって解凍するようにしたらいいんじゃないかと思ったけど、結局オプションを覚えてしまった
>>43 #! /bin/sh
wget -O - --quiet "$1" \
| sed -n '149,163p' \
| sed -r '0~2d
s/.*>([^<]+)<.*/\1/
s/晴れ/ /
s/曇り/ /
s/弱雨/ /
s/湿雪|乾雪|みぞれ/ /' \
| tr '\n' ' ' \
| awk '{ if ($7 == $8) $8 = "〃"
if ($7 == $8) $8 = "〃"
if ($6 == $7) $7 = "〃"
if ($5 == $6) $6 = "〃"
if ($4 == $5) $5 = "〃"
if ($3 == $4) $4 = "〃"
if ($2 == $3) $3 = "〃"
if ($1 == $2) $2 = "〃"
printf "|--+--+--+--+--+--+--+--|\n\
|00|03|06|09|12|15|18|21|\n\
|--+--+--+--+--+--+--+--|\n\
|%s|%s|%s|%s|%s|%s|%s|%s|\n\
|--+--+--+--+--+--+--+--|\n", $1, $2, $3, $4, $5, $6, $7, $8}'
そしてlibarchive化された FreeBSD の tar もそんな感じになんでもツールに
最近のlinuxのtarもzやjやJなしで解凍してくれるよな。 まあ圧縮するときにどうせ付けないといけないから結局覚えてしまうんだけど。
>>47 前時刻と同じかどうかのチェックと出力はまとめて
|awk '{for (i=1;i<9;i++){printf "|%s",$i==tmp?"〃":$i;tmp=$i};print "|"}'
としたい気分、スレ違い失礼
あれこれ覚えられない俺的には、tarが自動で何でも伸長して展開してくれる方がありがたい
53 :
ss :2011/12/27(火) 06:20:47.96
引数のうち、-で始まるものを除いた個数を数えるにはどうすればいいでしょうか? a.sh -a -b c d e => 3
>>54 #! /bin/sh
manko=0
for chinko in $@
do
if [ `echo $chinko | grep -v ^-` ] ; then
manko=`expr $manko + 1`
fi
done
echo $manko
>>55 "$@" の中に特殊記号とかスペースとか入ってたら駄目。
forとかでループしたりせずに一発でできる方法を想定してます。
n=0 for a in "$@";do case "$a" in -*) ;; *) n=`expr $n + 1` ;; esac done echo $n
> forとかでループしたりせずに一発でできる方法を想定してます。 ねーよ。
何でfor文周りたらいかんのかその理由を詳しく。 sedで一文でできたとしても下のレイヤではいくらでもfor文回ってるだろうに。
>>56 そういうのはUNIX系OSとは非常に相性が悪いので、至れり尽くせりのMFCとかを使うほうが捗るよ
61 :
54 :2011/12/30(金) 21:07:19.02
>>57 さんのを使わせてもらいます。ありがとうございます。
ちなみに
>>56 は別人なので。
むう。ID表示しない板ってのはややこしいな。
ていうかウンコとかチンコとかマンコとかオッパイとか、やらないか
>>56 を上司に提出したら殴られました。
なんで…
それは暴力事件かパワハラだから警察に通報したらいいと思うぞ。
なぜgetoptsを誰も利用せんの?
>>66 俺は単純なものとか、拡張する予定が無いときはつかわないなぁ
それに複雑な処理をするならば、RubyなりPerl使った方が簡単とかさ
>>66 こんな便利なものが!
getoptsを利用すれば、そもそも -で始まるものを除いた個数を数える必要もない
ことがわかりました。これで行きます。
まさに、forとかでループしたりせずに一発でできる方法ですね。
>69
チンコもマンコも使わなくていいって事ですね。 でもちょっと寂しいです。
getopts使ってもループは要ると思うが…
74 :
名無しさん@お腹いっぱい。 :2012/01/06(金) 01:39:38.05
あるプロセスを起動して、その標準出力から100行分の入力をもらったら、 そのプロセスを自動的に殺すようなスクリプトは書けますでしょうか? または、あるプロセスを100秒だけ起動して、その後自動的に強制的に殺すこと は可能でしょうか。
>>74 >あるプロセスを起動して、その標準出力から100行分の入力をもらったら、
>そのプロセスを自動的に殺すようなスクリプトは書けますでしょうか?
あるプロセス | head -n 100
でいいんでねえの?
>または、あるプロセスを100秒だけ起動して、その後自動的に強制的に殺すこと
>は可能でしょうか。
あるプロセス &
sleep 100
kill -9 あるプロセスのプロセスID
でいいんでねえの?
>>75 上の方法はあるプロセスが101行目を出力しようとするまで生きてないか?
困るの?
もともとの仕様は満たしてないな。
困るかどうかは
>>74 に聞かないとわからん。
$!って、拡張機能だったかと
ボケるならもうちょっと面白いの頼む
どうせ学校の宿題だろ そんなもん、動きゃいいんだよ
ボケてないよ。
ボケがウケなかったからって開き直らなくていいよ
>>75 ありがとうございます。
最初の問題については、たとえ延々と最初のプロセスが出力をたれ流していても、
パイプがなくなれば自動的に殺されるんですね。
後者の問題の場合、事前にプロセスIDが分からないのが問題なのですが、
シェルで、起動した命令のプロセスIDを取得する方法があるのでしょうか?
>>76 も
>>86 も、なぜこんな簡単なサンプルスクリプトさえ提示していただけないのでしょうか。
あるプロセス &
hoge=$!; sleep 100; kill -9 $hoge
>>87 変数が無駄だな
sleep 100; kill -9 $!
だけで桶。
あと、
>>76 の回答でわからない人間にはサンプルを示しても無駄。
その $! に入ってるプロセスIDは、Sleep のものだとわかった上で言ってるのでしょうか…
>>89 わかってないのはオマエ sleepのプロセスIDは $! に入らない。
確かに、
>>89 みたいなこと言ってる奴にサンプル示しても無駄だな。
正解者に間違った指摘する
>>89 とかは書き込み自粛してくれ
「バッググランドで実行された」 直前のプロセスID…だろw
>>88 で桶。
93 :
89 :2012/01/07(土) 15:55:44.03
自粛はしない。 すっげぇ数の訂正レスがついて嬉しい。ありがとう。
ばーれたか
普段シェルbashとか使用しませんが ファイルにある特定の文字でファイルを分割したいと考えています 何とか調べて 例えばkiritoriと言う文字の箇所からsample.txtを2つに分割するのに grep -n kiritori sample.txtで行番号がわかりますので split -ln sampl.txtによりxaa,xabの二つのファイルに分割することがわかりました ここでお尋ねしたいのですが grepとsplitをまとめて処理するためにはnをsplitに引き渡す方法がわかりません どうかよろしくお願いいたします 又他の方法が有りましたらお教えください
sed '1,/kiritori/{ w xaa d }' sample.txt > xbb
>>97 早速のレス有難う御座いました。
おかげでファイルを分割できるようになりました
cutで行番号のみ抜き出したり
sedは文字変換のみの認識しかなかったりで
にわかもんはあなたのスクリプト見ただけで
すごいなと言う感想のみです
たまには勉強します
有難う御座いました
bashのことで質問させてください。 dateでYYYYMMを取得してきます。(例:201201) 1月から9月の場合には0を消去して、YYYYMで表示させたいのです。(例:20121) 自分でも一応下のようにして出来たのですが、もっと簡単に作る方法はないでしょうか? lm=`date "+%Y%m"` ll=`echo ${lm}|cut -c 1-4` mm=`echo ${lm}|cut -c 5-6` if [ ${mm} -lt 10 ];then mm=`echo ${mm}|sed s/0//` fi lm=${ll}${mm} echo ${lm}
>>99 date +%Y-%m | sed s/-0//
>>100 それ、10月以降が駄目だろw
date +%Y%m | sed 's/-0//; s/-//'
>>100-101 自演乙 おちつけ
date +%Y-%m | sed 's/-0//; s/-//'
>>100-102 おぉ、もう返答が。
そうか、消したい0の前に何か付け足すことで限定すれば良いんですね。
ありがとうございました。
>>99 せっかくbashならdateコマンド以外、内部コマンドだけでもできるよ。
a=($(date +'%Y %m'))
echo ${a[0]}${a[1]#0}
month=`date +%m` case $month in 0?) month=${month##0} ;; esac lm=`date +%Y$month` or if you are using GNU date date +%Y%-m
bash環境ならGNU dateだろうし、
>>105 最終行の
date +%Y%-m
が最適解だな。
ところで、
>>105 前半のcase文は意味ない。場合分けせずに ${month#0}だけでよい。
>>99 です。
man dateで
>>105 さんのやり方がしっかり書いてありました…
お恥ずかしい。
皆様ありがとうございます。
いいね、これ。 今まで expr で 0 を消してた。
exprで0消しならこうか echo $(date +%Y)$(expr $(date +%m) + 0)
あるいは expr `date +%m` : "0\?\(.\+\)"
先頭に0が付いてると数値演算でハマることがあるよね $ echo $((08+0)) -bash: 08: value too great for base (error token is "08")
>>111 シェルの算術式とかでは頭の0は8進数扱いだからな。
exprなら8進数とはみなさないので、expr 08 + 0 とかやって0を消すのは常識テクニック。
質問させてください。 sed -e "s/ //g" temp.txt ↑ここに/(スラッシュ)を含む文字列を入れたいときはどうしたらいんですか?
sed -e "s/ /\//g" temp.txt
solarisのfindで、yyyymmddHHMMSS形式のディレクトリ一覧から、任意の日付以降のディレクトリを対象としてtarファイル化処理を実行したいと考えています 中間ファイルを作ってディレクトリ名と日付の比較を行なっての処理は一応出来たのですが、出来ればfind xargsで一発で出来る形にしたいです 中間ファイル無しで上記のような処理は実現できるでしょうか?
>>116 yyyymmddHHMMSS形式なら単純な数値と考えて大小比較すればいいね。
比較するのに中間ファイルは要らない。
>>117 エスパーカが足りないなw
中間ファイルは条件にマッチしたディレクトリリストのファイルかと
tarじゃなくてcpioなら Solaris findの -cpioオプションで一発かな
該当するディレクトリのタイムスタンプがディレクトリ名と同じになっていれば -newer のたぐいが使えるのでは?
>>119 -newer のたぐいはまさに中間ファイルが必要ですが
一番古い対象ディレクトリを指定すればOKじゃないかな。
最初の質問の中間ファイルを使う処理をスクリプトのまま書き込んだ方が話が早いと思うが… どんな内容の中間ファイルをどのような目的で作成しているのか それがわかれば回答する側もエスパーにならなくていいからね
皆さんの書き込みをヒントに自己解決しました。ありがとう。
125 :
名無しさん@お腹いっぱい。 :2012/01/19(木) 23:32:23.93
このファイルからランダムで1行だけ選択して /home/my/st/1.txt 1 暑い 2 寒い 3 少し暑い 4 少し寒い 5 すごく暑い 6 すごく寒い /home/my/st/2.txtに書き込ませたいですのですがどう書けば良いでしょうか?
cat 1.txt | shuf | head -1 > 2.txt
>>126 わお
そんなに短く出来るんですね
感謝です!!
shuf なんてコマンドあるんだ… ひとつ知識がふえた。ありがとう。 調べたらこんな感じにもできそうだった。 shuf --rndom-source=1.txt -o 2.txt
こう使う。 --random-source=/dev/random --random-source=/dev/zeroで試してみて
130 :
名無しさん@お腹いっぱい。 :2012/01/20(金) 01:03:57.15
Perlの本に、1行ずつ入力を読んで、ランダムな1行を残す方法が載ってたな。 全行シャッフルとかしなくていいのがメリットだとか。 perl -ne '$result = $_ if rand($.)<1; END{print $result}'
負担が軽いのが一番良いしそれが一番難しい
>>126 catもパイプも無駄だな。
shuf -n 1 < 1.txt > 2.txt
最初のリダイレクトも不要であろう…
shuf って GNU だけだよね?
グニュー特選隊
比較的最近のcoreutilsから へどらとかならあるんじゃね?
いやいや、5年くらい前からあるよ。
5年が最近なんだろう。
バグ出し終わるまで3年は寝かせるよな
ファイルからランダムに1行取り出すのにshufを使うのは 大手SIerじゃ5年前から常識だな
142 :
名無しさん@お腹いっぱい。 :2012/01/20(金) 23:18:45.09
shufはcoreutils 6.0(2006-08-15)からみたいだね。
改行区切りのテキストを、コマンドの引数で渡すために、コンマ区切りにしようとこう書いた A="`cat list.txt |tr -s \\n , |head -c -1`" でもこれだとnが,に置換される。\\nを'\n'にすればいけたけど、バッククオートの中のエスケープって何回評価されるの?
つ echo "\\n" \n
ログインするシェルってどうかいたらいいんでしょうか? ユーザーアカウント名とパスワードを自動で入れてログインしたいのですが
>>143 とりあえずcatが無駄。
バッククオートの中のバックスラッシュは特殊な意味を持つので、
2回評価されると考えとけばいい。
この例ではバックスラッシュ3回で回避できる。
>>146 $( )使っちゃ駄目よ。
俺も cat でファイル読む人なんだが、 なぜ cat をわざわざ付けるかと言うと、 自分が作る全てのスクリプトや打ち込むコマンドで ファイルを読む際には必ず cat で読む と統一する事で、ミスる可能性を減らしてるつもり。 客に納品するスクリプトでは仕方なく削るけど。 元々のきっかけは 20 年程前に tar でファイル消してしまったことだった。
無駄なcatを入れないのは大手SIerじゃ常識だね。
コンピュータ的には無駄だが人間的には無駄ではない。 コメントの様な物だ。
cat file | コマンド の順に書きたいというだけの理由なら、 < file コマンド と書けば良い。
152 :
143 :2012/01/21(土) 09:25:54.14
>>146 凄く参考になった。ありがとう
> バッククォートを使う古い形式の置換を用いたとき、バックスラッシュは文字通りの意味を保ちます
> が、 $, `, \ の前にある場合は例外となります。バックスラッシュが前置されていないバッククォートが
> あると、そこでコマンド置換は閉じられます。 $(command) という形式を用いたときは、括弧の間にある
> 全ての文字がコマンドとなります。特別扱いされる文字はありません。
`cmd`と$(cmd)の2つの形式で意味(処理?)が違うなんて知らなかった
> コマンド置換は入れ子にできます。バッククォート形式の時に入れ子を行うには、
> 内側のバッククォートをバックスラッシュでエスケープします。
入れ子にするときは2つの形式を組み合わせて書いてたから、これも気が付かなかった
特殊扱いの文字が$(cmd)形式ではないなら、cmdの中に)がある場合\でエスケープはできないってことか
>>147 評価回数について、ありがとう。最小3つ並べる必要があるのか
cat使っているのは、前処理があってパイプを使っているという意思表示
ときどきシーク可能か否かで挙動が変わるプログラムもありますし
>>147 > $( )使っちゃ駄目よ。
爺さんや、Solarisでも/bin/shはkshになりましたよ。
というわけでもういいんじゃないか。テンプレもそろそろ修正どき。
>>148 同じ様な経験から自分と似たような対処している全然知らない人の存在を知ると、何か和むなぁ
$( )を使わないのは大手SIerじゃ常識だね。
>>148 tar xvf と tar cvf を間違えたって話か?
ふつーあらかじめ chmod -w hoge.tar やっておくから消すことはありえない。
sudo tar cvf 〜 なんてしちゃったり
ftpmailで取得してた20年前じゃあるまいし、tarなんか消しちゃっても全然問題ないだろ。
tar cvf aaa.tar bbb ccc とやろうとして tar cvf bbb ccc とかやって、bbbを消しちゃったってことかな
あぁ、もともとのきっかけは20年前か… ftpmailあり得るな。
>>161 >>146 では「ファイルを読む際には必ずcatで読む」て言ってるから、
tar xvf の時の話かと。
164 :
148 :2012/01/21(土) 23:40:04.95
>>158 > tar xvf と tar cvf を間違えたって話か?
それそれ。
俺も先頭にcat付ける派。 cat foo | cmd1 で、cmd1の前に前処理やりたくなった時、 cat foo | cmd0 | cmd1 と書き換え簡単。 cmd1 fooをcmd0 foo | cmd1にするのは語順置き換えがある。 transpose-wordするのは空白入り"文字列やオプション指定があるとちょっと面倒。 ファイル名をひとつしか指定できないバカコマンドで、 2つ指定したくなった時にイラっとくるから、などの理由。
俺はcatつけないな。後段のコマンドにもよるけど、 ファイルがないなどのエラーを捕捉し損ねる可能性があるから。
むかし、cat foo | sed をここで書いて叩かれた思い出。
>>165 は
>>151 読んでないだろw
cat foo | cmd1 ではなく、
< foo cmd1 とする。(いつもこう書く癖を付けておく)
で、cmd1の前に前処理やりたくなった時、
< foo cmd1 | cmd2
と書き換え簡単。
以上で、catを無駄に使う理由がなくなる。
scshっていうシェル思い出しわ (| (< foo cmd1) cmd2) とかって書くやつ
>>168 流れが一方向ではないので理解しづらい。
そもそも<禁止ルールがある場合もある。
> <禁止ルール 俺ルールでは禁止って後だしで言われてもなあ。 w
>>170 良く見ろ。流れは一方向だぞ。
流れを一方向にするために、
com1 < file | com2
を
< file com1 | com2
と並べ変えたんだが。
>>170 は良く読んでなさそうだなw
知識の浅い上司に、直されることはある。 初心者でも読めるように cat から始めろ。 実績がないから cat から始めろ。 俺流を通す無能な上司を説得する方法も教えろください。
>>168 > で、cmd1の前に前処理やりたくなった時、
> < foo cmd1 | cmd2
逆じゃね?
後付けで無能な上司という制約条件だされてもなあ。そんなとこ辞めれば? w
>>174 で、cmd1の前に前処理やりたくなった時、
< foo cmd0 | cmd1
かな
いや、後付けじゃなくて便乗なんだけどね…
catなんてあんたのような無能かつ無用な上司。そんなプロセスは必要ないでしょ。
kill -9
>>178 > /dev/null 2>&1
何でもいいけど 引用レスの最初に入力リダイレクト書くと顔文字みたい > <
>>179 2>&1とか使うくらいならcshでやれよ頭固いなあ
cat
>>181 | tee -a 2ch.net 2> /dev/null
じゃあ俺はcatじゃなくてdog使うわ
cshを使わないのは大手SIerじゃ常識だね。
>>168 < foo cmd1は使えない。
!<でも
!cmd1
でもhistoryを呼び出せない。
>>186 シェルスクリプトでhistoryを使う馬鹿?
>>186 全力で己の無能を告白するなよ。ドMの新しいプレーか? www
!?cmd1
で呼び出せるだろ。
cat使うと複数でも処理対象がハッキリするから好きな書き方ではある。冗長だけどね リダイレクトじゃ複数は無理だし、多く引数を取るコマンド、特に入出力のファイル名を どちらも引数に取れるコマンドだと、入力だけ区別して分けられる
テキストファイルだけ扱うならいいけどバイナリファイルだとcat通すと0x1dが消えたりしてファイル壊すから危険。
読み取る側から見た場合、リダイレクトならシーク可能だけど
パイプはそうではないという違いもあるよね
つまりcatが単に冗長で資源の無駄、というだけでなく
単純にcatではダメなケース(あるいは非常に非効率になるケース)が
厳然としてあるわけで、
>>173 の上司にはその点を訴えてみたらどうだろうか
stdout/stderrを何かに保存する目的でいずれにせよリダイレクトは使うだろうし
パイプのほうがリダイレクトより「初心者でも読める」というのは意味不明だ
なんかほんの少しでも合理的な理由があるのだろうか?
>>189 バカな習慣を必死に言い訳すんなよ。羞恥プレー続行中か? w
複数ファイルを引数に取るのはどうすんだよ。
for f in $files ; cat $f |file -;done
こうか? スゲーぜ。 www
>>192 fileは普通標準入力から読み込ませることはしないだろ?シェルスクリプトで使うこと前提だぞ、スレ的に
>>190 何それ?
分割したバイナリを合体させるのに普通にcat使えるでしょ
catってfile結合コマンドだよ
>>191 ありがとう。
機会ができたら、訴えてみる。
「初心者でも」っていうのは、ちょっとニュアンスが伝えにくいんだけど…気にしないで大丈夫です。
展開の順序とか考えず、コマンドを並べるならなんでもかんでもパイプを通せばいいじゃんって
新人とかへ教えるのが楽だから、そういう(ローカルな)文化になってるのかも。
>>193 「ヒストリー使えないからダメ」とか言い出したのはやっぱり羞恥プレーか?
まあ、それは置いとくとして、「入力ファイルを区別できるからからcatして
パイプから流し込む」と言い出したバカをからかってるだけだよ。
入力ファイルは引数から渡した方が、
1 名前を渡せる。
2 シークも可能。
と、明らかに有利。
catはその名の通りファイルを結合する場合に使用する。
恥さらしな習慣の見苦しい言い訳まだ続ける?
世の中には、cat = catalog の略といわれて、からかわれてるのに気付かず信じるような 僕みたいなのもいるのですよ。 concatenate なんて…
>>191 リダイレクトってシーク可能だったのか、知らなかった。
でもシークできるかできないかで挙動を変えるのはプログラム側だよね?
プログラムの実装でわざわざstdinがシークできるかどうかチェックするロジックって普通実装してある?
シーク前提のプログラムはそもそも標準入力から読み込もうとしないんじゃないかな。
見苦しい言い訳をまだ続けるのか。 > プログラムの実装でわざわざstdinがシークできるかどうかチェックするロジックって普通実装してある? お前のようなボンクラは知らないだろうが、必要ならばしている。
>>198 fstat()で簡単に判断できるから、まともなプログラムならシーク可能かどうかは
「標準入力かどうか」ではなく、stat情報で判断する
ロジック的に1パス、シークエンシャルアクセスで行ける場合でも、
wavみたいなある程度でかいバイナリストリームを処理するソフトウエアでは
不要なチャンクをシークで飛ばせるかread()が必要かでは大違いなので
特にマルチメディア系ではシークが使える場合には使うのが普通
(そうしたプログラムがパイプで標準入力を利用可能なのも普通)
>>198 ざっとbinutils、grep、awk、sedのソース漁ってみてが、無いな
>>201 ボンクラがメクラ撃ちしたって当たらないって事の証明だな。
オレは一発でtailを見つけたが。w
lessもおそらくやってる。
wc -c 1GB_file # 一瞬 < 1GB_file wc -c # 一瞬 cat 1GB_file | wc -c # 時間かかる
>>203 これは俺にとって cat やめる理由になるな。
逆に言えばここまで出てきた書き込み程度ではあまり cat やめる気がしない。
でも何故だろうな。wc はソースしっかり読んだのに気が付かなかったなあ。
色んなシステムの様々なシェルスクリプトで共通的に関数を使いたいときって、どういう方法が 効率がよいだろう ・.profileとかで共通関数を定義する ・共通関数だけのスクリプトを作ってセットで使う ・がんばってシェルスクリプトに埋め込んでいく 他にある?
>>190 > バイナリファイルだとcat通すと0x1dが消えたりしてファイル壊すから危険。
どこのcat?
>>205 ふつうはファイル別にしてsourceする。
>>205 その 2 番目は source で読み込むという意味でOK?
. functions.sh
>>200 なるほどね。確かにfstatだと区別できる。とても参考になった
特に前に戻るシークしか考えてなかったから、後半はその通りだわ。酷いレベルで気付かなかった
システムコールのマニュアルは全部読んどくといい。 全部読んでも大した量じゃないから。
>>203 wcに似たプログラムを自分で作ったことがあるんだけど、wcの方が処理が速いわけ
んでなぜwcの方が速いのかソースを調べたことがある。すげえ勉強になったよ
>>207 >>208 そうさね
現状は、sourceで読み込ませてる
で、今は共通関数をfunctions.shとしてマージして使ってるんだが、対象システムで
使われてない関数も一緒になってるんで、サイズが無駄に大きくなってる
しゃあねえのかなぁ
適切に分割して必要な分だけ読み込ませりゃいいじゃないか。
シェルスクリプトの中で一行でpsql発行したいんだけどどう書けばいいかな postgresユーザに切り替えてからpsqlでselect文(time列から現在時刻の一ヶ月前からのデータだけをとる) 叩きたいんだけど TIME=1 sudo su - postgres -c 'psql -d データベース名 -c "select time from データベース名 where time > current_timestamp + '-${TIME} months';"' どうにもうまくいかない…ファイルとかにsql書いてやるのじゃなくて1行でやりたいんだけど。。
sudo su - postgres -c 'psql -d データベース名 -c "select time from データベース名 where time > current_timestamp + '"'-${TIME} months';\"" かなぁ
postgresユーザーで実行するコマンドをスクリプトにしておいて、そのスクリプトをsuで実行すればいいだけ >>ファイルとかにsql書いてやるのじゃなくて1行でやりたいんだけど。。 意味不明。
>>215 ありがとうやってみる。
>>216 別ファイル?にして呼び出すということでしょうか。すみません初心者なので
PGUSER=postgres PGPASSWORD=xxxx export PGUSER PGPASSWORD pgsql -d foo -A -q -c "SELECT * FROM hoge"; こんな感じでいけるんじゃないの?
select文の中で不等号と変数を使いたいんだ そこがわからない
zshの話?どこに使いたいの?
>>214 postgresのselect文の構文は知らないので、↓
select time from データベース名 where time > current_timestamp + '-1 months';
このselect文が正しい結果を返すと仮定して、
>どうにもうまくいかない…ファイルとかにsql書いてやるのじゃなくて1行でやりたいんだけど。。
この「どうにもうまくいかない」ときに、sudo su ... コマンドから
どのようなエラーメッセージが出されているのかを具体的に教えください。
ああごめん219は218へのレスです。 bashです。
223 :
218 :2012/01/24(火) 11:18:56.48
>>222 例えばMovableTypeへのアクセスだけど、これでいけたけど
psql -d foo -A -q -c "SELECT log_id,log_created_on FROM mt_log where log_created_on > current_timestamp + '-${TIME} month';"
su: option requires an argument -- c Try `su --help' for more information. months > chg_date;': -c: line 0: unexpected EOF while looking for matching `''months > chg_date;': -c: line 1: syntax error: unexpected end of file
上記のような感じです TIME=1 sudo su - postgres -c "psql -d データベース名 -c 'select time from テーブル 名 where current_timestamp + "-$TIME months" < time;'" 実行したのはこれです
>>225 ダブルクォートの中で素のダブルクォート使っちゃ駄目。
そこでクォートが終了して別引数とみなされて su 側でエラーになってる。
>>223 ユーザーを切り替えてからやるにはうしたらよいのでしょうかと
228 :
218 :2012/01/24(火) 12:52:46.68
>>227 postgres(root)でデータベースの実行をしたいだけだよね?
それを
>>218 で書いているわけだけど、それとも私が勘違いしているのかな
/path/to/doit ------------------ #/bin/sh TIME=1 psql -d データベース名 -c "select time from テーブル名 where current_timestamp + '-$TIME months' < time;" ------------------ # sudo su - postgres -c /path/to/doit
228さんごめんなさい 僕が勘違いしているのだと思います 教えていただいた方法でやってみます
教えていただいた方々ありがとうございました 228さんの方法で問題なくできました!
total_size=`fdisk -l $device | grep Disk | awk '{print $5}'` $deviceには/dev/sdbとか このスクリプトをsudoで動かすと、total_sizeが空 rootになって実行すると、容量の数字が入ります。 どうして?
PATHが通ってない。
234 :
232 :2012/01/26(木) 12:25:23.62
sudoってその辺の環境変数再設定しなかったっけ
>>232 sudoの中で変数に代入しても、sudoを抜けたら元のシェルの変数には入ってないよw
と、ボケておこう。
それボケなん?
238 :
232 :2012/01/27(金) 12:23:26.54
やったことをもうちょい詳しく。
つ total_size=`sudo fdisk -l $device | grep Disk | awk '{print $5}'`
>>232 $ cat ./test.sh
#!/bin/sh
device=/dev/sda
total_size=`fdisk -l $device | grep "Disk $device" | awk '{print $5}'`
echo $total_size
$ sudo ./test.sh 2> /dev/null
21474836480
242 :
232 :2012/01/28(土) 21:12:44.61
すいません、遅くなりました ~$ cat mksd.sh #! /bin/sh device=$1 echo $device total_size=`fdisk -l $device | grep Disk | awk '{print $5}'` echo "total_size = $total_size" ~$ sudo ./mksd.sh /dev/sdb /dev/sdb total_size = ~$ su パスワード: # ./mksd.sh /dev/sdb /dev/sdb total_size = 3904897024 です
243 :
232 :2012/01/29(日) 08:51:14.17
>>241 あれ、すいません見てませんでした
~$ cat mksd.sh
#! /bin/bash
device=$1
echo $device
total_size=`fdisk -l $device | grep Disk | awk '{print $5}'`
echo "total_size = $total_size"
size=$[$total_size / 2]
echo $size
saito@ubuntu:~$ mksd.sh /dev/sdb
mksd.sh: command not found
saito@ubuntu:~$ ./mksd.sh /dev/sdb
./mksd.sh: line 9: /2: syntax error: operand expected (error token is "/2")
~$ su
パスワード:
# ./mksd.sh /dev/sdb
/dev/sdb
total_size = 3904897024
1952448512
なぜ、こうなるんでしょうか?
>>243 面倒だから /proc/partitions の方使えよ。こっちならroot権限要らん。
1kバイトのブロック単位だから、1024倍な。
引数は /dev/sdaじゃなく、sdaだけで指定する。
grep/awkとか使わずに内部コマンドだけで組んでみた。
$ cat hoge.sh
device=$1
while read x x blocks name && [ "$name" != "$device" ]
do :; done < /proc/partitions
total_size=$((blocks*1024))
$ ./hoge.sh sda
1000204886016
245 :
243 :2012/01/29(日) 11:28:34.42
>>243 まだやってたんだ。
envやsetの出力差分とか見ないのか?
>>242 ↓の結果を比べてみる、とか。
#! /bin/sh
result=`fdisk -l /dev/sda`
echo "$result"
標準入力からデータを読み込むようなbashスクリプトを書いています。 スクリプトの途中でread -s -n 1などとして画面をポーズしたいのですが、 標準入力にデータが渡されているため画面ポーズのためのreadにもそれが読み込まれてしまい、思ったように動作しません。 一旦ファイルディスクリプタの0番をクリアすれば良いのかと思うんですが、どのようにすれば実現できるでしょうか? 念のため、画面の一時停止はsleepなどでも可能なのは分かっていますが、 今回はreadで実現したいということでよろしくお願いします。
>>248 read -s -n 1 < /dev/tty
>>249 出来ました!こんな簡単な事だったんですね。
ついでに聞きたいんですが、一旦読み込まれた標準入力のクリアとかって無理なんでしょうか?
それと/dev/ttyは移植性のある?書き方なんでしょうか。
質問ばかりですみません。
>>250 exec < /dev/tty
を実行すると、以降の行は標準入力が端末に戻るので
read -s -n 1
だけで行けるようになる。
/dev/ttyはどのOSでも移植性がある。
>>251 なるほど、そういうテクニックがあるんですね。
勉強になりました。
どうもありがとうございました。
>>251 流石に「どのOSでも」は言い過ぎではw
まあsh動く環境ならまず大丈夫だとは思うから実害はないが
254 :
名無しさん@お腹いっぱい。 :2012/01/31(火) 06:11:03.04
>>253 いいや、「どのOSでも」OK。
反論するなら反例を挙げろや、カス。
縛りはOSだけでいいの? じゃ MS-DOS を挙げよう。 UNIX系OS特有なんだし、少なくともPOSIXに準拠してなきゃ持ってないよ。
256 :
名無しさん@お腹いっぱい。 :2012/01/31(火) 08:27:24.42
>>255 お前ほんとにアホだなw
MS-DOS ではシェル(スクリプト)は使えない。
>>253 もとの質問の
>>249 read -s -n 1 < /dev/tty の readの -s -n オプションは
bash依存だが、/dev/ttyがOS依存なんて話は聞いたことがない。
テストスクリプトとして
----
#!/bin/sh
echo hoge > /dev/tty
----
があるとして、このスクリプトが「/dev/tty」が無いのが原因で動かないようなOSを
挙げてくれるかな。
>>253 よ。まあ、無理だろうけどw
>>255 >POSIXに準拠してなきゃ持ってないよ
/dev/ttyはPOSIX以前からあるよ
>>256-258 もうほっとけ。
質問者の質問に自分では答えずに、
正しく回答した回答者に後から間違ったつっこみを入れる
>>253 のようなアホは
いつの時代にも居るから。
FreeBSDでは/dev/ttyに直接アクセスしようとするまで存在しないのか。
アスペだらけのスレで「posixな」とか「シェルスクリプトが動く」などの制約を付けずに
> /dev/ttyはどのOSでも移植性がある。
と言っちゃった
>>253 の負け。
確かにそこだけ切り取ればWindowsも無いわな
>>255 MS-DOS版の sh.exeでは /dev/tty動くぞ。sh.exe内部で解釈してるらしい。
>>265 遅い原因は毎回md5sumを呼んでいるから
md5sum "$@"で求めておいて、その結果に対しての処理ならそれほど遅くない
アルゴリズムもcut -d' ' -f1してsortしてuniq -dして重複ファイルのMD5だけ列挙
そのMD5でgrepすればファイル名も分かるだろ
一気にmd5取る、md5でソート、ユニークなものだけ移動。残りは重複したファイル。 ユニークなファイルのリスト md5sum "$@" |sort -k 1 | uniq -w 32 |cut -d' ' -f 2
rsyncを--dry-runで走らせるくらいで十分、かつ速いんじゃないかと 何の検証もせず言ってみる
>>266-267 md5sumコマンド起動のオーバーヘッドより、
MD5計算時間の方がはるかに長いから、
毎回md5sumを呼んでも、ファイル名引数まとめてmd5sumを呼んでも
ほとんど改善しないよw
それより、まずはファイルサイズだけ見て、
同じファイルサイズのファイルが他にない場合は無条件でユニークなファイルとして
md5sum計算対象から除外した方がよい。
写真ファイルの同一検出ならファイル全体のmd5計算しなくても、 適当な位置で4KBくらい抜き出すのでもよさそうな
>>269 そんなところで高速化図ったんじゃねーよ。
見当はずれの言いがかり付けるって惨めだぞ。w
>>269 ソース読んでないだろwどのみちMac何だからそういう機能持ったアプリありそうだと思う。それ使った方がいい
読んだけどわからなかっただけだろ。
openって何だろうと思ったらMacにはそういうコマンドがあるのか。
で、openってなに?
$ open foo.txt $ open -a /Application/TextEdit.app foo.txt $ open -a /Application/Emacs.app/Contents/MacOS/Emacs foo.txt こんなコマンド。
適当なアプリ探して、バックグラウンドでそいつを渡すわけね
openはNEXTSTEP由来でファイルやディレクトリを開くコマンド
OSXのopenコマンドは open . でカレントディレクトリをGUIで開かせるってのが一番使うかな
blogに書いてろ
md5 でなんとかなる程度なら さいしょから samefile なり samesame でよいのでは
283 :
265 :2012/02/01(水) 17:06:16.13
284 :
265 :2012/02/01(水) 17:09:15.95
あ,最初で移動してたら次のmd5sumの$@がないて言われるね\(^o^)/
>>283 >>269 は全然わかってないマヌケな素人だから、奴の指摘は全部無視していい。
サイズなんて調べる必要ない。
286 :
名無しさん@お腹いっぱい。 :2012/02/01(水) 23:15:24.01
testコマンドで質問です。 man testを見てみると、以下の2つのオプションの説明があります。 1.-nオプションのところ True if the length of string is nonzero. 2.stringオプションのところ True if string is not the null string. これらの違いは、何があるのでしょうか?それとも同じなのでしょうか? 出来ればサンプルスクリプトで説明していただけると助かります。
stringオプション?
>>286 直接引用しろ。うちでは等価って書いてある
シェルスクリプトの勉強をしたいのですが、 何シェルがいいですか。
>>289 >>1 特記ない限り bourne shell ということは、それを選択すれば無難ということ。
Linux オンリーなら bash だろうけど。
>>289 そんな貴方に、Windows Power Shell。
自分が何調べてるかを理解してないだけに見える
オペレータだけ与えるとstringと解釈するのか。エラーにしろよお。
>>292 なんかUNIXのシェルより強力って書いてあるのが多いけどマジ?
「協力」の基準をどう考えるか次第でどうとでも
いま流行のステマとか
>>296 シェルそのものの機能は確かに強力だけど
肝心のコマンド資産がなさ過ぎて実用シェルとしてはなあ…
パワシェルはインタラクティブに使うとしょぼい。
301 :
265 :2012/02/04(土) 22:16:58.57
遅レスだけど、PowerShellは.Netのライブラリも呼べるしWin32APIも呼べるから、Windowsのシェルとしては強力だわ それを参考にシステムコールや動的ライブラリをロード・実行する機能を持ったシェルが作られたとしても 自分はあんまり使いたいと思わんな。そういう機能の需要と言うか必要性はあるのかどうか
PowerShellはいい加減スレ違いな気がするけれども…… その手の機能が欲しいときはぶっちゃけLL使えばよくね、と俺は思ってしまう それよりもシェルとしては以下の点がネックで、cmd.exeに比べてすら劣る ・デフォルトでスクリプトの実行が禁止されているので配布物でのスクリプト利用は 事実上不可能 ・入力リダイレクトが使えない ・オブジェクトパイプラインという一見高機能なものを備えているが、代償として バイナリデータをパイプやリダイレクトで扱えない 最後の問題が困る。外部コマンドをパイプでチェインする場合もPowerShellが 間に割って入って無駄にテキストに変換するので、データを壊すだけでなく 多分無駄に非効率でもある XPではそれに加えて我慢がならないほど起動が遅かった(ngen使っても)ので 遊んでみようという気にすらならなかったけど Windows7では起動時間は我慢できる範疇になったな
>PowerShellはいい加減スレ違いな気がするけれども…… だったらgdgd書かなきゃいい
>>303 >・デフォルトでスクリプトの実行が禁止されているので配布物でのスクリプト利用は
> 事実上不可能
うんこやん
質問です。 $ cat hoge $GLOBALS['hoge']['huga'] $GLOBALShogehuga とします。 $ grep $GLOBALS\[\'hoge\'\]\[\'huga\'\] hoge とすると、どちらの行も引っかかってしまいます。 $GLOBALS['hoge']['huga'] だけ引っかけたいのですが、どうすればよいでしょうか、ご教示ください。
$ grep "\$GLOBALS\['hoge'\]\['huga'\]" hoge
308 :
名無しさん@お腹いっぱい。 :2012/02/09(木) 23:05:25.02
grepに食わせるべきパターンが $ [ ] をエスケープした ¥$GLOBALS¥['hoge'¥]¥['huga'¥] なので、これをシェル的にクォートする必要がある。 シングルクォートでがんばるなら '¥$GLOBALS¥['¥''hoge'¥''¥]¥['¥''huga'¥''¥]' 正規表現として解釈されることを意図していないならfgrep使えば? とか思ったりもする。
>>306 $ grep -F "\$GLOBALS['hoge']['huga']" hoge
>303 すれ違いかもしれんが参考になった (unix shell 人視点の評価として)
>>310 すれ違いかもしれんが
> (unix shell 人視点の評価として)
こゆとき俺はこーかく
( unix shell 人視点の評価として )
>>311 そう書くとunixから定義しないといけない
ここはunix shell人のいるスレですね。
()は空白開けなくても大丈夫だろ。{}は必要だけど。
>>307-309 grep の件、man もロクに読まない私にお力添えいただき、ありがとうございました。
m(__)m
質問です。 あるスクリプトをホームディレクトリに作ったのですが、以下の条件があります。 ・他の人もそのスクリプトを実行できるようにしたい ・でもファイルの中身は他の人は見れないようにしたい。 このような場合、一般的にはどのような手法がとられるのでしょうか?
そういう無茶なことは考えない方がいい。
(chmod 0711じゃ)いかんのか?
319 :
名無しさん@お腹いっぱい。 :2012/02/13(月) 22:20:32.11
うちにあるsudoのパーミッションが -r-s--x--x で、実際実行はできるけど 中身はみられない。適当なシェルスクリプトを作って同じパーミッションにして みたけど、実行したらPermission deniedsetuidになってしまった。 (OSXにて)
320 :
名無しさん@お腹いっぱい。 :2012/02/13(月) 22:21:22.41
setuidというフレーズを消しわすれてしまった。
スクリプトはインタープリターに読んでもらわないと実行できない。 そして、インタープリターは実行する人の権限で動作する。 したがって、スクリプトは実行する人が読むことができる。できなければ実行できない。
つBATCOM
なるほどぉー
じゃあコンパイルできる言語で書き直すとか
UNIXサーバーの管理をしています。 ユーザーはスクリプトの実行は禁止ですが、 最近、ユーザーでも自分のホームフォルダーにスクリプトをコピーし、 X権限をすることによってスクリプトが実行できてしまうことが判明しました。 これはOSのセキュリティーボールではないのでしょうか? ユーザーのフォルダーではたとえX権限がされていても 実行できないようにする方法はありますか? 必要ならカーネルにバッチを当てる方法も、やもうえません。
>>325 > ユーザーはスクリプトの実行は禁止ですが、
なんか御幣のある言い方をしているようにも思えるが、つまりのところ特定コマンド
以外は実行させたくないんだろ?
であればログインスクリプトを制限がきつい奴にすれば出来る。
bash の rbash の項目の man page かググって調べろ。
.bashrc や .bash_profile などを個人で書き換えられないようにしておかないと意味が無かったりと
環境整備には手間がかかるとは思うが。
> ユーザーのフォルダーではたとえX権限がされていても
> 実行できないようにする方法はありますか?
以下を実行して↑に何の意味も無いことを学べ。
chmod 644 sample.sh
/bin/sh ./sample.sh
これ以上はスレチなのでここでの質問をクローズした上で、以上の情報を元に自分で調べるか
適切なスレに行って再質問されたし。
ネタだろ。 かまっちゃいかんよ。
mountにnoexecってなかったっけ?nodevはあったよな。
330 :
名無しさん@お腹いっぱい。 :2012/02/16(木) 02:11:23.48
コンパイルできるシェルはありませんか?
だから、コンパイルできるシェルはありませんか?
ありません。
>>330 int main(){return system("シェルスクリプト本文");}
って書けばコンパイルできるよ。
C言語上での文字列改行を行なえば複数行も記述できる。
shcの事か?
初心者なんですけど、16進数のテキストデータをシェルスクリプトでバイナリ化する事はできますかね?
printf '¥x68¥x6f¥x67¥x65?n'
>>337 これがヒントなんですか??
全然理解できへん(~_~;)
echo 686f 6765 0a | xxd -r -p
/etc/rcファイルを読んでるんですけど、 全く理解できません。 しょっぱなにこれが有るんですが、 stty status '^T' なんのためにあるのでしょうか? rcファイルが読まれ始めるときは、^Cや^Hが設定されていないという事? ですか? さらに、 if [ -f /etc/rc.first ] then . /etc/rc.first fi という一文は /etc/rc.firstが存在するならば、/etc/rc.firstを実行するという意味だと思うんですが、 -fオプションはググると 「file が普通のファイルならば真となる。」 とありましたが、普通ではないファイルって有るんでしょうか?
普通ファイルをそういう意味で捕らえるのはフレッシュ過ぎて噴いたw懐かしさがこみ上げてくるレベル
CP/Mあたりだと、普通ではないファイルを使った階層化ができなかったなw
>>340 UNIXではデータを書いたり読んだりするいわゆるファイルの他にも
OSが管理している資源やその他の物に名前をつけてファイルとして
扱うことができる。
デバイスファイルやディレクトリ、ソケット、シンボリックリンク、その他。
「普通のファイル」って訳は最近では一般的なのかね? 「レギュラーファイル」でいいんじゃないかと思うが。
>>336 「16進数のテキストデータ」はどこにあって、どういう形式なのか?
「バイナリ化」するとは具体的にどういうことか?
元の「16進数のテキストデータ」はバイナリではないのか?
Unicode文字のエスケープ表現か何かなのか?
>>344 regular fileに対する確立された訳語は「通常ファイル」じゃないか。
test -f FILE 「FILEが通常、ファイルなら真になる」 通常はファイルならば真なんですね。通常じゃない時は真にならないんですか?
348 :
名無しさん@お腹いっぱい。 :2012/02/20(月) 21:50:38.98
ディレクトリにテストしてみれば一発やん。 test -f /etc/passwd && echo file || echo 'not file' test -f /etc && echo file || echo 'not file'
-fのfは普通のf
testコマンド(というかそれを内蔵しているシェル)のバージョンによっては、 デバイスファイルやソケット、FIFO等でも test -f は真になる。 よって、test -fをレギュラーファイルかどうかのテストに用いてはならない。 豆な。
そんなシェルあるんだ…
なんだそれ。-e の存在意義は。
ほら、ツメキリとか。
>>354 -e が追加されたのは割と最近。純正/bin/shのtestには-eがない。
ねーねー,「純正/bin/shのtest」ってナニ? /bin/testとは別に /bin/sh の built-in コマンドがあるという主張?
何か馬鹿が湧いてきたな。反応しちゃいかんよ。
>>358 釣られてあげよう
(ba|z)sh 辺りを /bin/sh として symlink/hardlink して使ってれば built-in だわな
ash ベースでもコンパイルの仕方によっては built-in になるし
純正なのに bash/zsh なの?
363 :
340 :2012/02/23(木) 00:58:08.13
普通のファイルの意味はわかりました。 ところで /etc/rcの先頭に >stty status '^T' が有るというのは、 rcスクリプトが読まれ始めるときは、sttyの設定がされてないので rcスクリプトから実行されるプログラムの ステータス情報をキーボードから^Tと入力すれば表示できるようにするため に設定していると言う理解で良いでしょうか?
$ (ba|z)sh
365 :
名無しさん@お腹いっぱい。 :2012/02/23(木) 01:37:03.64
うちのsttyにはstatusって指定できないから意味自体分からんのよな。
>>363 デフォルトの設定がユーザを混乱させるからなんじゃないかな。
> ステータス情報をキーボードから^Tと入力すれば表示できるようにするため
多分違う、^Tを入力するとカーネルに対して、「何か」をしろという指令が非同期に飛んでいく。
カーネルはユーザーの端末に対してメッセージを出すことはしない。
「何か」が何なのかは、statusなんて機能は使ったことないから知らない。
"stty status" でググるといろいろ出てくるね。
screenコマンドのstatus lineみたいな奴。 表示する方法、される内容はカーネル、端末依存。
大量のメールアドレスの一部分をマスクしたい。例えば
[email protected] → foo****@example.com
ドメイン部分はそのままで、先頭3文字程度残して、残りの部分はメールアドレスの文字数が変わらないように
任意の文字で埋めたい。今は下のように変数にメールアドレスを入れて処理しているけど、ちょっと不恰好
[email protected] MASK='*'
RC=3
DOM="${MADR##*@}"
let MC="${#MADR}"-"$RC"-"${#DOM}"-1
echo "$MADR"
echo "${MADR:0:$RC}`yes "$MASK" |tr -d '\n' |head -c"$MC"`@$DOM"
もう少し楽に処理できないでしょうか?
素直にrubyで
echo
[email protected] | ruby -pe '$_.sub!(/(?<=[^@]{3})[^@]*(?=@\w+)/){|s|"*"*s.size}'
perlならもっと短くできるんじゃないかなぁ。
>>370 sedを使うのはいかが?
echo "
[email protected] " | sed -e 's/\(...\).*@\(.*\)/\1...@\2/g'
ユーザ名が必ず3文字以上ならこれで良いはず。
ユーザ名が2文字以下だとそのまま出力される。
(元のスクリプトでも2文字以下ならそのままっぽいが。)
長さ保存してないじゃんそれ
>>373 あ、長さが変わらないように、か。
「長さが分からないように」と読み違えてた。すまん。
>>370 をもとに、おもにyes|trの部分を改良してみた。
不要なクォートや不要な変数も削除した。
↓
[email protected] MASK=*
RC=3
DOM=${MADR##*@}
echo "$MADR"
echo "${MADR:0:$RC}"`echo "${MADR:$RC:${#MADR}-RC-${#DOM}-1}" | sed "s/./$MASK/g"`@"$DOM"
つーか、見るからに遅そう。 > 大量のメールアドレスの一部分をマスクしたい。例えば 千通突っ込む気にならない。
awkでやってみたよ。 RC=3 MASK='*' echo "$MADR" | awk -F@ -vn="$RC" -vm="$MASK" '{t=substr($1,n+1,length($1));gsub(".",m,t);print(substr($1,1,n) t "@" $2);}'
速度優先ならC言語一択だろ。 標準入力から1行ずつ複数のメールアドレスを読む仕様。 gets()使うなとか、エラーチェックなしとかの突っ込みはなしな #include <stdio.h> #define RC 3 #define MASK '*' int main() { int i; char buf[1024]; while (gets(buf) != NULL) { for (i = RC; buf[i] != '@'; i++) { buf[i] = MASK; } puts(buf); } return 0; }
379 :
名無しさん@お腹いっぱい。 :2012/02/25(土) 11:10:48.60
シェルスクリプトスレでなんという暴論
速度がそんなに重要じゃないからここで聞いてんのにな。
>>380 >>370 >大量のメールアドレスの一部分をマスクしたい。
速度が重要という質問ですが・・
だが正論。これをシェルスクリプトでというのはコスト高くないかな
「大量」としか言ってないじゃん。 量は多いけど時間は多少かかってもかまわないんでしょ。
たとえば退社前に処理を開始して 次の日の出社までに終わってればいい、なんてケースだと 7時間が4時間に短縮されてもあんまり意味ない。
皆さん、レスありがとう御座います
初めは
>>372 のように考え、どうしても長さが保存できないので何かやり方は無いかと質問しました
>>371 ,377
もっとさくっと書けるコマンドがあるかなと思っていたけど、やはりスクリプト言語使うしかないですか
それにしてもrubyは短く書けるんですね。今のシステムには入れていませんが勉強になります
>>375 なるほど。任意の長さの文字列を作るのにsedで置換を使う方法は思いつかなかった
それを元にすると最終的にこんな感じでしょうか?
[email protected] MASK=*
RC=3
DOM=${MADR##*@}
MINV=${MADR:$RC:${#MADR}-RC-${#DOM}-1}
echo "$MADR"
echo "${MADR:0:$RC}${MINV//?/*}@$DOM"
これなら、外部のプログラムを呼び出さないのでそこそこ速そう
ただ、bashで動くことは確認したけど、汎用性を考えるとawkを使う
>>377 ?
速度についてですが、何度も変換するものではないし、
寝ている間に終わればいいなと思っていたのでシェルスクリプトで十分でした
訂正:echo "${MADR:0:$RC}${MINV//?/*}@$DOM" → echo "${MADR:0:$RC}${MINV//?/$MASK}@$DOM"
Å ヽ('A`)ノ、スーパーちんぽマン参上!! / ( ) \ んヘヽヽ〜'
# Set shell to ignore SIGINT (signal 2), but not children; shell catches # SIGQUIT (signal 3) and returns to single user after fsck. trap : 2 trap : 3 # shouldn't be needed という一文が有るのですが、 SIGINITとSIGQUITを無視(ignore)するならば trap ' ' 2 trap ' ' 3 と言う書き方になるような気がするんですが、 :はどういう意味が有るのでしょうか?
>>388 trap '' 2 は、
親(シェル自身)も子プロセス(外部コマンド)もSIGINTを無視する。
trap : 2 は、
親(シェル自身)はSIGINTを無視するが、子プロセス(外部コマンド)はデフォルト動作に戻
る。
あと、' ' じゃなくて '' (空文字列)な。
半二重なら trap : 2、全二重なら trap : 2と trap : 3が要るんじゃねーのー
>>389 >>390 :ってヌルコマンドって奴ですか?
そうすると、
親(シェル自身)はSIGINTを無視するが、子プロセス(外部コマンド)はデフォルト動作に戻る
という解釈どうして出てくるかさっぱりなので、教えてください
お願いします
trapがそういう仕様だから。man読め。
シェルのマニュアルのtrap項目だと、指定コマンドが空文字列だと そのシグナルを無視し、子プロセスも無視するとは書かれているけど、 これだけだとわかりにくいかも。 trapで何らかのコマンドを指定すると、それはシグナルハンドラが設定されるので、 シグナルの一般仕様により、シグナルハンドラが設定されている場合の子プロセスでは シグナル設定はデフォルトに戻る。 よって、ダミーのシグナルハンドラを設定するために、: コマンドを指定している。
awkで複数のファイルに対して一括処理するときに変数xを初期化したいのですがうまくいきません。 何が間違っているのでしょうか? BEGIN{x = 0} printf("%d\n",x++) END{x=0 }
awkがそういう仕様だから。man読め。
>>394 BEGIN{}等は使わない
↓
#!/bin/awk -f
FNR==1{x=0}
{printf("%d?n",x++)}
>>391 ":"がnull commandなのは先頭語に出てきた場合だけ。
trapが第一引数の":"をどう解釈しようと自由。
ただnull commandからの類推で「無視するが〜」としただけ。
>>397 ちがうよ。
trapは、第1引数を改めてコマンドとして解釈する(2回解釈する)ので、
結局 : は先頭に出てきたのと同じで、null command として解釈される。
(eval : の場合と似てる)
trapが:を特別に解釈しているわけではない。
たとえば、trap true 2 って書いても trap : 2 と同じ。
むしろ特別に扱っているのは""の方。 これでSIG_IGNにすることになってる。
awkのフィールド分割的なことやるのに while read hoge hage ; do : done <file とかよくやるけど、1行の文字列を分割しようとして echo "hoge hage" | read hoge hage ってやってみても、$hoge にも $hage にも何も入らない なんで?
そういう仕様じゃないから
kshだとできるよ。
echo "hoge hage" | { read hoge hage echo hoge=$hoge hage=$hage }
>>403 おおー入った! \(@o@)/
どういう仕様になってるんだろう
サブシェル的な問題?
>>404 その通りだが、そうならないシェルもある。自分なら read hoge hage <<<"hoge hage" って書く
ヒアストリングってbash/zsh以外でも使えんの?
古典ヒアストリングならな。
ソラリスのkshは冷やすとリング使えないのに、 リナックスのkshは冷やすとリング使える不思議
409 :
400 :2012/02/28(火) 22:39:16.48
ヒアストリングってスレの初めの方で出てたやつですか オイラの読んだ入門書には載ってなかったんだよなぁ と思いながら試してみたら Syntax error: redirection unexpected sh -> dash なうちのDebianじゃダメみたい (・ω・` ) ステキな機能だけに残念 やっぱこういう場合はset使うべきなんですかね…
>>403 じゃまずいの?
一行で書きたいならセミコロン
echo hoge hage | { read hoge hage; echo hoge=$hoge hage=$hage; }
411 :
名無しさん@お腹いっぱい。 :2012/02/29(水) 02:06:19.12
getoptsにて「-yx」のように複数文字のオプションを判定することは可能なのでしょうか? xxx.sh -a test -yx #!/bin/ksh while getopts a:yx opt do case ${opt} in a) YY=${OPTARG} echo "オプション[-a]の引数は${YY}だよ。" ;; yx) echo "オプション[-yx]があるよ。" ;; esac done
>>411 getoptsでは、-yx は -y -x と指定したのと同じに解釈されるから無理。
代わりに --xy を使うとよろし。
>>413 すみませんが詳しい方のみ回答をお願いします
ああ --yx か。とにかく
>>412 のいう通りってこった。
getopts y: として $OPTARG が x かどうか判定すればいいんじゃね? -y x も受けつけちゃうけど。
417 :
名無しさん@お腹いっぱい。 :2012/02/29(水) 14:08:24.59
どうもこんにちは〜 list=`cat ./file | grep aaa` って感じでlistにaaaを持つ行を全部放り込んでるのですが、 これらを別々の1行ずつに分割して なおかつlistを配列にして格納する事はできますか。 具体的には、fileの中にはaaaの文字列を持つ行が5つあるのですが それをlist[0]〜list[4]に格納したいのです。 よろしくご指導お願いしますm(_ _)m
なんで cat 通すんだろ。 grep aaa file でよくね?
>>417 IFSに改行コードのみを代入した状態で、list配列に一括代入する文法を使う。
#!/bin/bash
IFS='
'
list=(`grep aaa file`)
420 :
名無しさん@お腹いっぱい。 :2012/02/29(水) 16:42:01.73
421 :
400 :2012/02/29(水) 23:33:48.87
ロングオプションは getopt でいけるけど何か問題もあったんだっけ
>>410 パイプ通すとブレースもサブシェルで動作してるのか
外からは参照できないみたいなんですよね
いやもちろん最初の例もサブシェル作ってるんですが (;´Д`)
処理の内容にもよるけど、やっぱりグローバルで使いたいってなると
関数に括り出してバッククォートで呼んだりして結局同じようなことなのかなぁと
そんな感じの意味です
でも勉強になりましたみなさんありがとう
>>421 getopt(外部コマンド)はスペース入りファイル名などの引数を正常に扱えない
などの仕様バグの固まり。getoptsを使うべし。
とあるソースから #define HOGE MAGE HOGE の定義値を抽出したい。 grep HOGE header.h |grep define |awk print $NF みたいな書き方(うろ覚え)すると キャリッジリターンも拾うわ、 タブ(スペース)数でフィールド変わるわなんですが うまい方法ないですか?
>>423 $ cat header.h
#define HOGE MAGE
$ (cat header.h; echo HOGE) | gcc -E -P -
MAGE
プリプロセッサに置き換えられるからプリプロセッサに置き換えさせるとかワロタw
でもうまい方法でしょ?
#ifとか考え出したらそれ一択。
複数行に渡るマクロもあるしな。 けどお題はもっと単純な話なんじゃないのかな。 マクロの展開を止めたいなら、 (#define MAGE 〜があってもMAGEを出力したい場合) awkスクリプトになってしまったが、こんな感じ。 awk '$0 ~ /^#define[ ]+HOGE/ { $1=""; $2=""; print $0 }' []の中はスペースとタブ
質問です。 あるディレクトリにある全部のファイルに対して コンパイルをかけるスクリプトをつくりたいです。 TESTLISTには ソース名 コンパイラオプション が書いてあります(hoge.c 5みたいに) --------------------------------------------- #!/bin/sh # プログラム、コンパイルオプション一覧リストを指定 LIST=/home/shell/TESTLIST # コンパイラのパスを設定 CCOM=/home/shell/cc.sh # コンパイルをかける while read ARG1 ARG2 do ${CCOM} ${ARG1} ${ARG2} done < ${LIST} -------------------------------------------- のような簡単な奴で良いんですが、
続き cc.shの中に、 -------------------------------------------- if [ ${RETCD} -ne 0 ] then echo "コンパイルログを表示しますか?" RCV="" while [ `echo "${RCV}" | sed -ne '/^[ ]*[yYNn][ ]*$/p' | wc -l` -eq 0 ] do read RCV done if [ `echo "${RCV}" | sed -ne '/^[ ]*[yY][ ]*$/p' | wc -l` -ne 0 ] then more ${コンパイルログ} fi fi ------------------------------------------- のように書いてあり、コンパイルに失敗した場合、 「コンパイルログを表示しますか?」が端末に表示されたままで、「N」や「Y」を 入力しても反応がなく、Ctr-Cで実行を打ち切っている状態です。
続き コンパイルに失敗した場合、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はいじれません。
>ちなみにMakeは使用不可です。また、cc.shはいじれません。 この状況を何とかした方が建設的かと。
>>431 > でオッケーでしょうか?
つまり俺たちにデバッグしろと言っているのか?
はい
はいじゃないだろうが!
はいじゃないが
はいはい。
438 :
名無しさん@お腹いっぱい。 :2012/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を読ませる。
>>438 おいおい、そのリダイレクト方法だと結局同じ理由で駄目だよ。
標準入力を退避しておいて復帰する。
exec 3<&0
while read ARG1 ARG2
do
${CCOM} ${ARG1} ${ARG2} 0<&3
done < ${LIST}
>>439 の方法でもいいが、
>>438 が言いたかったのは
↓じゃないかな
exec 3< ${LIST}
while read ARG1 ARG2 0<&3
do
${CCOM} ${ARG1} ${ARG2}
done
>431 > でオッケーでしょうか? オッケーだと言う人がいたらしいよ。 ただし私は、貴方の環境と責任を共有していないので、自己責任でやって下さいね。
テキストから読み込んだ文字列内の「\\」をそのまま変数に入れたり表示させたりする方法を 探しています。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
つread -r
普通はread -rだけどbashは知らん。
>>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
>>446 > bashでもread -rは「Backslash does not act as an escape character.」だそうです
と書きたかったのか?
AとBの処理があって、 Aを開始、 Bを開始 Bの中でAの処理中を待つことできますか? 意味わかりませんかね・・・ mkdirとかロック待ちみたいなやつです。
ロック待ちがわかるんなら、そのまんま A で mkdir lock して B で [ -d lock ] かければ? while 文で無限ループ作って、sleep でも挟めば十分「処理待ち」になると思うけど。
>>448 FreeBSDなら lockf(1)、Linuxならflock(1)を使ってなんとかしろ。
カレーライスとライスカレーみたいなモン
うまいなあ。それイタダキマス。
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というファイル名のファイルを全て削除し、その数をカウントする」 何がおかしいのでしょうか?
>>455 4が表示されるのはオカルト。君もうすぐ死ぬんじゃない?
ファイルを削除して数をカウントしたいだけなら
find ほにゃらら -print0 | xargs -0 rm -v | wc -l
でよい。変数もforも必要ない。
4が出るのは君がオリジナルのスクリプトをここにコピペするときに何か端折ったせいだろう。
>>456 ごめんなさい、a=$(($a + 1))が抜けてました...
にしてもこんなにコンパクトになるもんなんですね
ありがとうございました
xargsは原始人の道具。 find ほにゃらら -exec rm -v {} + | wc -l で良い。
-deleteが使えるfindもある find ほにゃらら -delete -print | wc -l
>>458 -exec の方が古い感覚だけどどうなんだろ?
>>460 -exec ';' なら古い感覚
-exec + は新しい感覚
462 :
460 :2012/03/11(日) 08:29:08.31
>>460 + はいま使っているマシンの中では使えない物がほとんどかも。
-exec は元々 Unix に魅せられたポイントなので、1989 年には使ってた。
xargs はネットで教えてもらって 1995 年頃から使い始めた。
けど確か元からあったかも。
>>462 -exec + はSolarisでさえ使えるのに、どんな古いOS使ってるんだよ?
POSIXにも入っていてSVR4由来(当然Solarisにもある)でHP-UXにもあるのに、
使えないのを探す方が難しいよね。
原始人と言われたからってムキになってウソを教えるのは良くないな。
http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-210.html | 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 {} +
ちょっと前までテンプレにfindの項があったと思うが、今は無くなってるな。 確かテンプレではfind -print0 | xargs -0推奨で、スレ内議論では-exec +を使えと主張する人がいた。
テンプレにあったのはfind -print | xargs という回答には必ず言いがかりが付け られていたから。質問者のためではなく回答者のためのテンプレ。 -exec {} + 構文が紹介されてからはxargsを使う意味がなくなったのか削除された。 それでもしばらくは-exec {} + を知らない原始人がいたけど、そのたびに原始人と 呼ばれて、絶滅していった。テンプレから削除されたのはこの時点(絶滅後)かも。 -exec {} + ですべてが置き換え可能とは言わないが、find+xargsが必要になること は極めてまれ。
うーむ、結局その2つ違いって何ですか? あと、パイプで繋がってしまっているrmを画面にも出力する方法ってないんでしょうか?
468 :
460 :2012/03/11(日) 10:44:50.32
俺が xargs 教えてもらった頃は -exec は fork するから良くないと言われてた。 + は SVR4 に入っているのなら俺のもだいたい動くね。 でも俺まだ Tower の SVR2 や SVR3 とも格闘してるから。 ファイル名の長さが 14 文字までのやつ。
>>467 2つの違い
-print0や xargs -0は使えないOSがある。
>パイプで繋がってしまっているrmを画面にも
tee
>>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
> -print0や xargs -0は使えないOSがある。 例えば? どっちも相当昔からある気がするけど
>>471 ちょっとは自分で調べろよ。Solarisで-print0等が使えないのは常識。
473 :
460 :2012/03/11(日) 11:04:39.92
結局、自分が使ってるOSで使える方法を使えって結論になってるよね毎回
答える側は質問者の環境を想像すべきだな。 SVR[23]のような骨董環境前提の回答なんか意味ない。
それなら結局xargsでも-exec +でもどっちでも良いんじゃない?十分に新しいLinux/*BSD環境前提なら。 自分はタイプ数の多いxargsは使わないけどね。 無用な-exec \;と-0無しのxargsさえ避ければ良い。 そもそも今回は-deleteが使えるならxargsも-exec +も要らないし。
>>477 だから、使える方法を使えばいいってことでしょ?
結論見えてないの?
>>470 > 3 ファイル名に改行入れられるとヤバいので-print0, -0が設けられた
改行というか、広い意味での空白($IFS)だな。
xargsは、$IFSの改行/スペース/TABだけじゃなく、 シングルクォート/ダブルクォートも解釈しちゃうという問題がある。 it_don't_mean_a_thing.mp3 とかのファイル名もそのまま通らない
こういうイヤーンなファイル名があるときって、makeが通らなくなって難儀する。 コロン(:)が含まれてるファイル名なんか最悪。。 FILES = $(wildcard *.mp3) $ make hoge Makefile:〓: *** multiple target patterns. Stop.
なんかもう素人の集団みたいになってるな
基本的な歴史としては
>>470 の通りなんだが
現代においてはfindで引っかるファイル数が数十万〜数百万ということも珍しくなくなった
そしてそのような場合{} +では処理できない、というか渡された先が悲鳴を上げる
だから 5. としてxargsを-n付きで使うようになったわけ
>>481 みたいな問題にもちゃんと解法はある、つーかググレカス
ゆえに{} +はファイルを渡す先が確実に処理できると確信できる場合だけ使うべきで
癖をつけるなら-print0 | xargs -0の流れが正しい
何か問題が起きてもxrgsにオプション足すだけで解決する
つーか、初期の頃はちゃんとそう説明する奴が居たはずだけどな…
>>483 > 現代においてはfindで引っかるファイル数が数十万〜数百万ということも珍しくなくなった
> そしてそのような場合{} +では処理できない、というか渡された先が悲鳴を上げる
<limit.h>に従った正しいプログラムなら何の問題もないです。
> だから 5. としてxargsを-n付きで使うようになったわけ
これはあほなプログラム向けです。
不特定個数の引数をとれるという仕様にもかかわらず悲鳴あげるのはバグ。 引数の個数に制限がある場合にはxargs -nも有効だが、そんなヘナチョコ コマンド出会ったことない、具体的には何?
というわけで2006年以前のfindutilsを使う可能性がある人は、 バグがあるので -exec {} + はやめたほうがいいということになるのかな
>>483 は渡された先が悲鳴あげるといっているので、それは違う。
もっとも、
>>483 がその区別をつけられないだけかも知れないが。
結局
>>483 はボケ老人のタワゴトって結論でいいですか?
・悲鳴あげるヘナチョココマンドの存在は不明
・
>>481 のようなケースも-print0, -0で対処できるている。
>>489 >>481 はそういうことを言ってるんじゃない。
>>480 が $IFSだけが問題と言っているのでは誤解を生じるので、
それだけじゃなくクォートも、と言う話。
まあxargs対策でエスケープすればいいんだから、findの出力をfilterするなり解法はあるわな。 > 何か問題が起きてもxrgsにオプション足すだけで解決する こっちのほうが問題では。
GNU findutilsは、デリミタを指定すると(-d, -0)、quoteは無視するようになっている。 他のfindは使ってないので知らないが。
print0でNUL文字を区切りにしたんだから、ファイルシステムに
許されているいかなる文字もこれで対応でしょ。
> 何か問題が起きてもxrgsにオプション足すだけで解決する
その問題とは?
>>483 のボケた脳内にある悲鳴あげるコマンド
しかないのですよ。
今までなかったからこれからもないと信じるのはどうなのと思わなくもない
お前らって、本当、どうしようもないバカだよな ちったぁ議論らしいことをしたいなら、前提について定義しろよ お前ら何のOSの事を想定してんだ?Solarisか?AIXか?386BSDか?バージョンは?え? 使ってるコマンドはどこの物だ?OSについてきたコマンドか?GNUのやつか?バージョンは?え? そこが全然明確じゃないから、いっつもいっつもループしてんのか前に進んでんだか 前にも進んでないんだか分からねえグダグダ展開になってんじゃねえか お前らの脳内それぞれで、前提狂った状態で、全然違うOSの事で話をしてたって、 意味も価値も実りある結論も、何もありゃしねえんだよ お前らって、本当、どうしようもないバカだよな
結局どっちがいいの? find . -print0 | xargs -0 -I{} mv -vb {} ../tmp とかした時って同名なのにバックアップ取られないファイルがあったんだけど、-exec +ならちゃんとバックアップされる?
>>497 バカからも得られるものはあるものさ
バカってのはこういう事を考えてるんだ、こんな風に誤解してるんだ、その程度しか知らないんだ、
じゃあ分かってない人はその辺が分かっていないのかもしれないから、ちょっと注意しよう
そんな目線での考察や気づきは、やっぱりバカからしか得られないものなのさ
分かりやすい自演
>>498 find、xargs、mvの仕様、及びファイル名の状態(空白含んでるとか、日本語ファイル名だとか)次第
どんな名前のファイルがこようがこれなら何でもOKという万能包丁は、ぶっちゃけ無い
FAQにも割とマジで"Use Samba and explorer.exe"ともある
バックグラウンドで何かを起動すると、 ジョブ番号とPIDが表示されるじゃないですか。 あれって表示させなくする方法ってあるんでしょうか? 時間のかかる処理をバックグラウンドで走らせて その間に別の処理をやって、waitで同期する、 みたいなことをやるスクリプトで、邪魔なんですよね。
505 :
名無しさん@お腹いっぱい。 :2012/03/12(月) 23:21:09.67
bourne shだったりcshだったり。 Solarisです。
csh使うのやめろ shは出ない
509 :
265 :2012/03/13(火) 00:27:03.89
>>508 find . -exec cp -vb ../tmp +
find: -exec: no terminating ";" or "+"
だって・・・
510 :
265 :2012/03/13(火) 00:27:31.16
まちがえた find . -exec cp -vb {} ../tmp +
結局、print0 とかが必要になるのは Windows でファイルを処理しきれなかった時ばかりなので Unix 上のコマンドじゃなく Windows ネイティブな UNIX-Like tools が 完璧なファイル名対応出来ればいいんだけどな。 Unix 上ではそんなファイル作らない。
みんなそんなに移植性必要なの?
> 結局、print0 とかが必要になるのは > Windows でファイルを処理しきれなかった時ばかりなので 違うよ。root権限で動作するスクリプトが毒食わせられないための用心。
>>512 移植性が必要ならシェルスクリプトなんて使わないよ
ワンライナー手打ちするだけならそれこそどうでもいいし それ以上気を遣いたいんなら、単にLL使えばよくね Perlなら昔から標準でfind2perlとかついてくるし
シェルスクリプトを作る際の考え方はある程度使いまわせるが、移植性は低いわな実際 まぁ考え方っつっても、それは別にシェルスクリプトでしか習得できない考え方ではないけれど
autotoolsの中の人に聞かせてあげたい
移植性のために数多くの制約に縛られるなんてのは、 シェルスクリプト的に本末転倒なことなのさ
いや、移植性を突き詰めていくとシェルスクリプトで全部やるという結論に至る。
幸か不幸か自分のやりたい作業はシェルスクリプトで済んでしまう。perlもpythonもいらない。 だから(個人的には)シェルスクリプト GREAT! だね。
質問です。 cp a.txt b.txt というシェルスクリプトが書かれた『hoge.sh』をダブルクリックで実行した場合、 普通はなんの反応もなく、コピーが実行されます。 これを、実行されたコマンドを端末に表示させることはできるでしょうか? はじめから端末内で bash hoge.sh とすればいいのですが、深い階層にあって面倒なので…。 それに、この場合も何のコマンドが実行されたのかが分かりません。
>>521 hoge.shに以下のように書いておく。
xterm -e sh -xc 'cp a.txt b.txt; set +x; echo -n Hit any KEY:; read key'
>>522 ありがとうございました m(_ _)m
tarって入力されたデータをそのままの順でアーカイブするけど -Tで渡すファイル名をソートする意味ってあるかな?
tarはアーカイブの先頭からファイルを展開していく 遅いテープに書き込むときに、早めに参照したいファイルをアーカイブの先頭付近に書いておくと 早めに展開される そんな特性があるので、その特性を活かすためにアーカイブするファイルの順序を指定することは、 意味がある わざわざソートして渡してるなら、その特性を理解してないだろうから、意味ないだろう
526 :
名無しさん@お腹いっぱい。 :2012/03/15(木) 21:04:05.76
どなたか↓わかる方、今週末中にお願いします。 ──────────────────────────────────── 不定個数の整数の引数を与えて実行すると,それらの整数のGCMとLCMを計算して 表示するようなシェルスクリプトを作成せよ.使用シェルは/bin/shとする. 【実行例】 $ ./kadai15.sh 12 20 24 GCM = 4 LCM = 120 ────────────────────────────────────
GCMとLCMがわからん
lcmは最小公倍数だね。 gcmは最大公倍数? w
Greatest Common Measure
Least Common Multiple
>>528 はアホ
最大公倍数 最小公約数
本当にどうでもいいことだが、gcm ってメジャーなんでしょうか? 普通の数学では gcd が圧倒的で、gcm は数学教育の教科書でしか 見たことがない。
数学板で聞いたら。
SEだが
>>526 がわからんくて死にたい。
整数と小数の判定ってシェルでどうやんの?
535 :
531 :2012/03/16(金) 01:13:58.15
メジャーなんですねgcmだけに、と無理矢理言っておきます
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
>>536 不正解
引数 12 20 24 の時、
gcd:12 lcm:120 と表示される。
正しくは GCM = 4
あと、/bin/shでは動かない $(( )) とか
>>537 freebsd の /bin/sh で動いたが
>>538 >>1 >FreeBSDユーザは/bin/shの正体がashなので注意。
それより、GCMの計算が間違ってるので結局ダメ
>>537 Solarisも/bin/shはkshになっちゃいましたよ、おじいちゃん
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 なってるよ。おじいちゃん用のshは/usr/sunos/bin/shに隠居しました。
>>544 なってないよ。
opensolaris ≠ solaris
あと、pdkshになってるopensolarisだとしても、
「正体はkshだから注意」ということで/bin/shのお題の回答としては不正解。
ぷぷぷ
Solarisなんていつまであるんだろうなぁ。
$((expression))がサポートされてなければexprに書き換えれば すむ事だから大した問題じゃないよね。 多分、/bin/shってお題はcsh使うなカスって意味だろうね。 おじいちゃんはこんなところで重箱の隅つついてないで、外へで てゲートボールのエースでも目指した方がいいよ。
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 :2012/03/16(金) 11:44:30.22
>>548 >多分、/bin/shってお題はcsh使うなカスって意味だろうね。
違います。従来からの/bin/shを使えという課題です。
>大した問題じゃないよね
それでは課題として点がもらえません。
大した問題かどうかは関係なく、課題通りの答が必要です。
引続き回答をお願いします。
表示形式も含めて課題です。
あらkshからbashになったのね。> Oracle Solaris 11の/bin/sh
553 :
526 :2012/03/16(金) 12:23:58.00
私の為に争わないでください 課題の回答だけお願いします
>>552 えっと……どこをどう読めばそうなるのかとても不思議
>>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 :2012/03/16(金) 14:45:06.16
時間が無い。早くしてください。 来週の月曜の朝10時までにお願いします。 過程とか不要です。答えだけ書いてください。 もし回答以外のことも書きたい場合はスクリプトを*で囲って 目立つようにしてください 書き方の例を示します **************************** a = 3 x + y = 5 ****************************
今それどころじゃないからちょっと黙ってて。
ここまで、 「宿題は自分でやれ」 「来年はちゃんと講義聞こうな」 なし
分からない人は黙っててください
>>560 それって、お前も黙らなきゃいけないんじゃないか?
すべて分かった上で言ってるんだよ。
**************************** #! /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で。 大学生はもう春休みなはずだが、実習? それともこれだけできれば単位が貰える系か? # 今年は進級できるかなあ、自分。
>>563 だからぁ、bashじゃ駄目だっておっしゃってますが・・
>>548 > $((expression))がサポートされてなければexprに書き換えれば
> すむ事だから大した問題じゃないよね。
letは使えないの?
もうできてる人が何人もいるんです
3/19の10:00まで待つと書きましたが、前倒して3/17の16:30までとします
>>557 にあるフォーマットでお願いします
>>563 最大公約数求めるのに引数デクリメントしながらすべて割って試すとか
総当たりの非効率アルゴリズム使ってボケるんなら、
最小公倍数でもインクリメントしながら順番に割って総当たりするアルゴリズムで
ボケるべき。
つか, /bin/sh って言ってる奴いるけど, どの時点でどの機能が入った
/bin/sh まで許せるんだ?
FreeBSD の ports で拡張機能すべて許可した v7sh では func(){}
すら Syntax error なんだが...
# 少なくとも ``#!/usr/bin/env bash'' くらいにしないと販促だ
>>563
>>566 バカ共の相手が面倒になったので締め切りました。
やっぱりバカしか居ないんだな。
なりすまし多いね
>>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
自演も多いよ
本人です
3/17 17:00までに提出しないと単位が足りなくなるのが分かったので質問してます
レポートに貼り付けるのは私がしますので、3/17の16:30までにお願いします
また他の皆さんについても、ソースにバグがないかどうか、早急なチェックとデバッグを
期待しています
>>557 にあるフォーマットでお願いします
そろそろ飽きたわ。もう十分釣れただろ
ていうかもうできてんじゃないの?確かめてないけど
編集前ディレクトリと編集後ディレクトリを比較して、 変更がないファイルを編集後ディレクトリから削除する シェルスクリプトを書こうとしています。 diffをディレクトリ同士で実行し同名ファイルを探し その同名ファイルをdiffし返値が空なら削除という操作を 再帰的に階層を掘って実行すれば良いと思うのですが、 どうも何から書けばいいのか詰まってしまいました。 奇特な方居ましたらアドバイスお願いします。
>>578 オプションよく読んでいませんでした。
読んで出直してきます。ありがとうございました。
>>577 目的に対する作業の方法が間違ってる気がする。
何のために「編集前ディレクトリと編集後ディレクトリを比較して、
変更がないファイルを編集後ディレクトリから削除する」のか
を書いた方が、適切な答えが帰ってくると思う。
>>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 :2012/03/17(土) 07:30:38.91
>>572 さんありがとうございます。/bin/sh命令のみですね。
これで提出します。
>>572 こんなバカみたいな総当たりはダメだって言われちゃいました
もっと数学的な解法をアルゴリズム化したものでないとダメです
結果が正しければいいってレベルじゃないんです
100万とか1000万とか、それ位大きな値になると、ちっとも終わらないじゃないですか
期限は今日の16:40までとします
くれぐれもよろしくお願いします
>>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"
>>577 LANG=C diff -qrs a b の出力結果でなんとかする
というかバージョン管理システムを使うのが良い気がする
A=*.txt B=$A touch $B とすると、"*.txt"というファイルが出来てしまうんですが これ$Bを展開させたいときはどうすればいいんですかね
>>586 本当に
>>586 のとおりに実行したのなら *.txt は展開される。
展開されないのはカレントディレクトリに *.txt にマッチするファイルがないから。
すでにファイルがなければ展開しようがない。
588 :
586 :2012/03/19(月) 12:56:05.81
>>587 ヒントありがとうございます
oppai.txt がある場合⇒ oppai.txtにタッチ
oppai.txt がない場合⇒ *.txt を作成
という動きになりました
まーこれはこれで使い物になりませんわ
存在をチェックしてからtouchすればいいじゃない。
>>588 もし「存在しなければ作成したくない」という意図なら、
touch -c $B で桶。
>>586 エスパーすると、
A=*.txt
B=$A
mv $A /どこか
touch $B
みたいなことをやりたいのでは?
それなら、
A=`echo *.txt`
mv $A /どこか
touch $A
で桶。変数はAだけでよい。
592 :
586 :2012/03/19(月) 14:20:52.93
>>590 天才や・・・ UNIX板には天才がたくさんいる
みんなありがとう
いや、みんなは普通だよ。
おそらく A=*.txt で *が展開されなかったから Bに代入し直せば再解釈されて展開されると勘違いしたのだろう
結局、どこで展開されたんだろうね
ん? A=*.txt でも B=$A でも 変数直接代入時は展開されないよ。 touch $B みたいにクォートなしで参照した時に初めて展開される。
599 :
586 :2012/03/19(月) 19:58:57.99
>>598 ありがとう。それだけが心残りだったんだ
shを作ったBourneは天才だね。
601 :
名無しさん@お腹いっぱい。 :2012/03/19(月) 20:08:20.98
あのソースコードは勘弁して欲しい。
ソース読んだのか あんたスゲーや
603 :
名無しさん@お腹いっぱい。 :2012/03/19(月) 22:06:26.63
http://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に置換されるのでしょうか?
> [ ! = 'q' ] これはそのように解釈するtestもあるから注意しろ。くらいでいいと思う。 > どのような解釈をすると、!cがtest cd /etcに置換されるのでしょうか? ヒストリ置換だろ。
>>605 今の時代、そのエラーが出るshを使っている人、いるのかね?
今の時代、 [ ! = ! ] [ [ = [ ] [ ] = ] ] [ = = = ] [ -f = -f ] など、すべて文字列の比較として期待通りに動作する
しかし未だに [ x"$hoge" = x"yes" ] などと書いてる人を見掛けるな #!/bin/bashとか書いてるのに
スクリプトインジェクション対応だよ
[ "$hoge" = yes ] だとして具体的にどうインジェクトするんだよ
>>611 どうインジェクションするか解説お願いします
hoge=']; /bin/sh;'
ってゆーか、こういう場合は case "$hoge" in yes) ...;; esac って書くよね、ふつー。[Yy][Ee][Ss] なんかに変えるのも簡単だし。
>>613 >>610 はダブルクオートで囲ってるから、[コマンドの第一引数として$hogeの中身が渡るんで、そのhogeの値はそのまま[コマンドが解釈する。
どうあがいてもインジェクションなんて無理だと思うんだが。
てきとーに言ったんだろ。 もうカンベンしてやれ。
本人乙
違うよ。
最近のJavaScriptのようにeval使いまくりで威張る奴か。
全部持ってって〜
>>606 $ busybox ash
$ hoge=!
$ if [ "$hoge" = 'q' ]; then echo QUIT; fi
ash: q: unknown operand
https://uec.usp-lab.com/SHELL_TIPS/CGI/SHELL_TIPS.CGI?POMPA=TIPS_not_while に
>シェルスクリプトに制御構文が増えることを極力避けるように様々な工夫をしている。
>制御構文を避ける理由はコードが読みにくくなるためだ。
>これまで制御構文whileやforのはずし方について書いてきた。
>処理速度を高速化するためにwhileやforをコマンドに置き換えるというのは、
>それなりの効果が期待できる方法だ。
>シェルスクリプトに制御構文であるforやwhileが出てきたら、
>何か避ける方法がないか探してみるとより高速なスクリプトが書けるようになるかもしれない。
ってかいてあって、いろんな例が書いてあったり、
変なパッケージ(python製)を入れて、そのコマンドを使ったりしてるんですね。
僕は制御構文外すと逆に可読性がおちたり、
pythonで書かれたコマンドを呼び出すより、シェルスクリプトで制御構文書いた方が
早いと思うんですけど、おかしいですかね?
質問です。 以下のようなファイルがあるとします。 ----------------- 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
お前はマニュアル読むという事を考えたことが無いのか?
>>624 うん、sedの超基本的な使い方で出来る
627 :
名無しさん@お腹いっぱい。 :2012/03/21(水) 23:34:53.13
sedを使えばいいと思うよ
>>623 そのページを見て思ったことは、xargsは便利だね、くらい
>>623 シェルスクリプトに限らず、プログラム書く時に(一部の)制御構文を使わないってのは個人的に良くやる。効率とか性能とか抜きで。
ゲームの縛りプレイみたいなもんだけど、意外なテクニックを発見したりできて楽しめるよ。おすすめ。
上司や同僚に見つかったら
>>623 のサイトみたいな適当なウンチクで誤魔化せばOK。
>>624 sed で 2行目から5行目は 2,5。
hello を good byに置換するには s/hello/good by/
接続すると 2,5s/hello/good by/
>>629 BASICのころはあったけどな。
if文分岐とかで速度差が出ないようにするとかで。
今はそういうのする必要ないけど。
PerlやC#、COBOL、Fortran、アセンブリなんかも、見慣れてなければ読みにくく 感じるものさ
Whitespaceもな。
俺はsedが嫌いなので、できるだけperlを使うようにしている
それは報告しなくてもいいです。
kshで待ち行列を作りたいんですが、どうしたらいいでしょう? 基本動作はキューなんですが、 1 2 3 ↓1を実行 2 3 1 2 3 ↓2を実行 1 3 としたいです unset 配列[N]でインデックスを詰めてくれればこんなの楽勝なのに…
位置パラメータ使う。 $ set -- 1 2 3 4 $ shift $ echo $@ 2 3 4 $ set -- 1 2 3 4 $ set -- $1 ${@:3} $ echo $@ 1 3 4
>>636 unset array[N] で要素をunsetした後に、
array=(${array[@]}) でセットしなおせばインデックスは詰まる。
>>638 とは違って位置パラメータを壊さずに済む。
シェルスクリプト学び始めたばかりの初心者です。 ・ファイルを指定フォルダ内へコピー ・同名ファイルが存在する場合は、 既に存在するファイル名を「ファイル名 (1)」へ変更し、 既に「ファイル名 (1)」が存在しているのであれば、 それをさらに「ファイル名 (2)」へ変更し、、、(繰り返し) というシェルスクリプトを書きたいんですが、 既に「ファイル名 (*)」が存在する場合に*の数字を どのようにすれば知ることができますか? *さえ知れたらexprを使えば出来るとは思うのですが... アドバイスお願いします。
>>641 逆に考える。
変数iとかに1を入れておいて、
"ファイル名($i)" が存在したら
iをインクリメントして "ファイル名($i)" にリネームする。
643 :
名無しさん@お腹いっぱい。 :2012/03/23(金) 22:28:54.51
再帰使わないとややこしいことになりそうだな。
最小の空きを使うんでいいの? i=1; while [ -f "file($i).txt" ]; do i=`expr $i + 1`; done; echo $i
645 :
名無しさん@お腹いっぱい。 :2012/03/23(金) 22:52:22.20
「それを」が何を指すかによる。
GNU cp なら --backup=numbered とか?
647 :
名無しさん@お腹いっぱい。 :2012/03/24(土) 01:18:46.16
なんか見覚えがある処理だと思ったが logrotate かいな。
>>641 つまりアヌスを知りたいと……教えてあげよう
>>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
突っ込みどころ多いな
もっと単純にこうだろ。 第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 :2012/03/24(土) 21:11:20.76
皆さんアドバイスありがとうございました。 642さんの意見を参考に書いていたら、 651さんとほぼ同じようなものが書けました。 勉強になりました!
その書いたものをさらしてくれると みんなも勉強になるんだけどなぁ
#!/bin/bash [ -e "$2" ]&&{ i=0; while [ -e "$2($((++i)))" ];do :;done; set "$1" "$2($i)";} cp "$1" "$2"
rm -rf -- * ってどういう風に解釈すれば良いんですか? -- って正規表現ですか? *はファイル名ですか?
656 :
名無しさん@お腹いっぱい。 :2012/03/25(日) 10:59:50.45
>>655 その * は glob。シェルが解釈する。
シェルが展開して rm に渡す。
-- は正規表現でも何でもなくて、ただの --。
シェルは特に何もしない。
そのまま rm に渡される。
657 :
名無しさん@お腹いっぱい。 :2012/03/25(日) 11:00:45.80
rm が -- をどう解釈するかは man rm に載ってるはず。
658 :
名無しさん@お腹いっぱい。 :2012/03/25(日) 11:28:39.15
- で始まるファイル名(コマンドからはオプションに見える)に マッチしたときのための策だな。
でも rm -- が使えるのは GNU rmだけだから、使わない方がいいな。
>>659 調べたらBSD系はgetopt(3)つこうてるから--大丈夫だよと書いてあったんだけど
他のUNIXはまた違うの?
BSD以外のUNIXってあるの?
ねーよんなもん
Solarisのmanには、BSDユーザーのために仕方なく -- が使えるようにしてあるが、 将来は -- が使えなくなるので注意、と書いてあるね。
ワイルドカードを使うときは rm ./* みたいにすれば引数の先頭が - になることはない。 --が使える保証がなければこっちで。
この手の問題って rmだけじゃなく cp mv ln等全部なんだよな。 で、-- が使えない ln で、-sという名前を指しているsymlinkを作ろうと、 ln -s ./-s hoge ってやると、hoge -> ./-s というsymlinkができて、 symlink自体に ./ が含まれてしまって美しくない。 -- が使えない条件で 、hoge -> -s は作れないものか。
リンク作る部分をスクリプト言語に投げるとかは? じゃあ全部スクリプトでやれよみたいな話になりかねんからダメかね
>>664 昔からUnixやってる奴は普通そのやり方だよな
--指定してても、引数に./*でなく*を指定するのは違和感を感じる
特定のフォルダのpngファイルを見つけて 「◯◯◯.png」というファイルを見つけました と表示させたいのですが、なるべくコンパクトにするにはどのようにすればいいでしょうか? 自分のやり方だとbasenameで失敗してうまく表示されません あと、そのフォルダにpngファイルがなかった場合は何も表示しないようにしたいです。 find ${DIR}/ -name "*.png" -exec echo "「`basename {}`」というファイルを見つけました" \;
>>668 find "$DIR" -name '*.png' -printf '「%f」というファイルを見つけました¥n'
>>668 `basename {}`はfind実行より先に展開されてしまうので、
{}という文字列のbasenameが実行されて無意味になっているのが原因。
GNU findなら
>>669 でよし。
>>668 find "$DIR" -name '*.png' -exec sh -c 'for f;do echo 「`basename "$f"`」というファイルを見つけました;done' - {} +
質問です。 開始日付と終了日付を指定したら、その間の日付を出力するスクリプトを作りたいです。 イメージとしては以下のような感じです。 $ ./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 --------------------------------------------- よろしくご教示お願いします。
日付まわりはシェルでやるとめんどいから perlとか使っちゃう。
> 以下の処理までは作ったのですが、ここから先が思いつきません。 dateをつかってこんな感じかな ステップ1. 今日の日付を20120301のように出力しよう ステップ2. 20120301のような日付を、UTCエポックからの秒数に換算しよう ステップ3. UTCエポックからの秒数を、20120301のような日付に変換しよう ステップ4. 20120301のような日付を受け取り、その翌日の日付を出力しよう ステップ5. ループを回して指定範囲の日付を全て出力しよう ※UTCエポックは 1970-1-1 00:00:00 UTC
>>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
>>676 bashならこっち
for (( t = stime; etime >= t; t += 60 * 60 * 24 )); do
date -d @${t} '+%Y%m%d'
done
678 :
676 :2012/03/28(水) 00:53:33.92
添削ありがとう
>>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'
}
>>680 forループ中、dateが1回無駄になってる。せっかく$tに入ってるのでそれ使え。
for ((t = stime; t <= etime; t=$(date -d "$t 1 day" '+%Y%m%d'))) {
echo "$t"
}
682 :
680 :2012/03/28(水) 07:10:47.88
添削ども
683 :
名無しさん@お腹いっぱい。 :2012/03/30(金) 14:34:15.36
標準出力に日付をつけたいんだけど かっこいい方法ありますか?
エスパー、日本語解読しろ
>>683 #!/bin/sh
while IFS= read -r line; do
echo "`date`: $line"
done
∧∧ ヽ(・ω・)/ ズコー \(.\ ノ 、ハ,,、  ̄  ̄
ていうかあの文章がわからないとかギャグだろ
もうcat --dateでいいよ。 誰かパッチを送れよ。
俺は command > $(date +%Y%m%d) って意味かとオモタ
>>690 目的はロギングだな、と想像できれば、毎行にタイムスタンプつけたいんだな
ということもわかる
>>691 目的はロギングだな、と想像できれば、ログファイル名毎に日付を入れたいんだな
と考えるのが自然
まぁもう解決したんだからそれでいいんじゃね。
俺は touch -t YYMMDDhhmm /dev/stdout って意味かとオモタ
俺はプロンプトに日時を入れるのかと…
自分はdate > /dev/tty みたいなことかと思った
>>680 それだと、1900年とかそれ以前とか、32bit版の場合の2038年以降が動かないし、
GNU dateに依存するのもいやだし、
dateコマンドに頼らずに20120301等のの数字を直接操作して計算する方法ないですか?
頑張って書けば可能だけど、 月の長さや閏年とか考えると、GNU dateかLL使うのがいいですよ。 コマンド組み合わせるのがシェルの得意なところだし。
>>698 GNU date使っても epoch以前の日付には対応できないだろ、って言ってるのでは?
昔のこと考えたって、そもそも日本が西暦になったのは明治からだぞ 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
>>700 江戸時代でもそれ以前でも年表は西暦で記述されてるから無問題。
1752年の件も含め、紀元1年以降対応できれば幸いです。
紀元前までは要りません。
702 :
名無しさん@お腹いっぱい。 :2012/03/31(土) 19:29:56.45
localeをイタリアにしたら1582年に暦が切り替わる実装もあるのかな。
>>704 20120301 等の数字だけ処理できればいいので、曜日は無視でいいです。
>>704 曜日以外はできたのか。じゃあ早く回答してやれよ。
$ 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 できてんじゃん
じゃあ環境に依存しない方法を自分で考えてくれ 「すべての環境」に対応するのは骨が折れると思うが 期待しているぞ
>>711 >>697 の言うように、20120301等の数字を直接演算すればそもそも環境依存しない。
その演算が場合分けとかでややこしいだけで。
>>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 ← 閏年だよ
>>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
$ 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
>>714 1700年はまだグレゴリオ暦に切り替わってないのだから、
1700年は閏歳が正しい。
別の例として、
1500年は閏歳なのだが、
calでは閏歳(正しい)
GNU dateでは平年(間違い)
いずれにしても GNU dateでこの年代の日付処理はできない。
西暦年が100の倍数の時、 1700年以前なら単純にすべて閏年にする。 1800年以降の場合は、400の倍数でない年のみ平年に戻す。 で桶? case文バリバリでだれかシェルで組んでくれ。
718 :
名無しさん@お腹いっぱい。 :2012/04/01(日) 17:54:49.44
厳密にやるためには国や宗教の情報が必要になるので あまりしゃかりきにならんでええ。 日本は1872年かな。
日本においては閏年の算定を皇紀を用いて行うことが法令で定められています
>>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
>>720 西暦999年以前がダメ。頭に0付け加える処理が必要。
723 :
名無しさん@お腹いっぱい。 :2012/04/03(火) 20:05:15.60
ファイルがあるかないかだけを調べる標準のコマンドありますか? [ -f /tmp/unko ] よりかっこいい方法募集
724 :
名無しさん@お腹いっぱい。 :2012/04/03(火) 20:06:28.95
test(マテ
「標準のコマンド」とは?
>>725 まず入ってるであろうコマンドのことだよ
coreutils と読み替えてもらっても結構
この程度で揚げ足取ったつもりなのが笑える
つまりシェルビルトインコマンドは禁止ということですね
ls /tmp/unko > /dev/null 2>&1 && echo yes || echo no
>>723 < /tmp/unko 2> /dev/null && echo ある
(< /tmp/unko) 2> /dev/null && echo ある
testと[って同じだって書いてあるけど、]の立場はどうなるの?
] は [ の引数
testの引数にはならないの? $ test -f /tmp/unko ] -bash: test: /tmp/unko: binary operator expected なんかエラーでた
自分が [ って名前かどうかで、 ] が最後にあるべきかどうか判断するんだよ
>>736 うぉぉ マジだ。 test.c ってこんなことやってんのか。
はぁー 無駄にすげぇーなー
20年遅れてるスレ行けよ。何でいまさら誰でも知ってる話題でこのスレ無駄使いしてるの?
test -e
かっこいい(笑)
評価基準がよくわからん。
それがわからん。
教えてください 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=」がくっついてるし... これってどういう風に解釈すれば良いんでしょうか?
set a b c for i; do echo $i; done とかやってみれ
750 :
名無しさん@お腹いっぱい。 :2012/04/04(水) 23:31:20.38
for に in がない場合は位置パラメータ($1 $2 ...)を使う。 位置パラメータをiにセットしつつforループを回して、 $iが term=* のパターンにマッチしたとき、 そのなんたらの部分(*にマッチした部分)をexprで抜き出して 変数termにセットする。 位置パラメータ全周したらその時点の $term を出力。 というconsole関数。
751 :
名無しさん@お腹いっぱい。 :2012/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 ----------------------------
>>751 awkで、getlineを使わずに普通にできる。
ただし、数字は半角で書いてないと計算できない。
754 :
名無しさん@お腹いっぱい。 :2012/04/05(木) 13:03:00.03
>>753 すみません、やり方がわからないんで・・・
後で出します;
755 :
名無しさん@お腹いっぱい。 :2012/04/05(木) 13:06:43.25
>>752 getline を使わずにですか・・・
ちょっとヒントいただけますか?
>>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 :
名無しさん@お腹いっぱい。 :2012/04/05(木) 13:33:45.35
>>756 お〜、有難うございます!大変助かります!
半角にして試して見ます。
ちなみに
$0 テキストファイル
といった具合に、テキストファイルを引数にして読み込み処理する、というようなことも出来るでしょうか?
>>757 引数にしたかったら、
>>756 のしたから2行目の done のところを done < "$1" に修正すれば良い。
あと、入力ファイルはあらかじめソートされてること
759 :
名無しさん@お腹いっぱい。 :2012/04/05(木) 13:42:26.55
>>758 すごい!
自分もこんなにあっさりスクリプトが書けるようになりたいものです・・・
758 さん、有難うございました、大変勉強になりました。
awkなんてAhoでもできることなのに
ディレクトリのmvできるかどうかを事前にチェックしたい 特定のディレクトリ以下に アクセス不能とか移動不能なものが あるかどうかを調べたいんですが、findでいいですかね
だめだ、難しい グループでOKになってるときのパターンがネックだ これのせいでワンライナーにならん
>>762 find . ! -readable | wc -l
でダメ?
765 :
sage :2012/04/10(火) 19:58:25.17
for i in {1..10}; do command 1> ${i}.txt 2> ${i}.log &; done とかやると, [1] + suspended (tty output) ... とかなって処理が終了しない.なぜぇ・・・
それはね…
;が邪魔だって文句いわれたから、 はずして実行したら {1..10}.txt とかできたぞ どうしてくれる マジレスすると、commandの中身なによ
769 :
sage :2012/04/12(木) 10:33:02.93
Cで書いたプログラムだね.
commandはシェルビルトインコマンドでしょ
というか、
>>765 実行してもそういう現象は起きないので、
回答欲しかったらもっと具体的に "how to repeat" 書いてくれ
>>765 そのcommandのプログラムがSIGTTOUをSIG_DFLに戻してしまってるんだろ。
普通ならシェル側でSIGTTOUはSIG_IGNにするからsuspendはしないようになってる。
>>771 Steps to Reproduce だろ
>>773 How to repeatで合ってる。というか、そんなところに突っ込んでも面白くない。
775 :
名無しさん@お腹いっぱい。 :2012/04/12(木) 22:19:43.60
再現性の話ならreproduceがふつー
SIGTTOUについて答えられない奴が持論の英語を主張して話題逸そうとしてるなw
「バグの出し方」と書かれてる文章に、 「バグの再現手順」だろ? と突っ込んでるようなモン。
>>765 エスパーするとzshの最近のバージョンでのバグ。
w3m & で起きる奴とおんなじ.どうすればいいんだろ・・
何のこと?
>>780 set +m
で、ジョブコントロールを無効にすれば桶。
ただ、シェルスクリプト中から起動すればデフォで set +m 状態なんだがな。
コマンドラインから直接起動してるのか。
どこに書いていいのかわかんないから、ここに書いてみる。
shell script書いててはまったんだけど、
ls -l /etc | sort -k4 -n
がファイルサイズでソートしてくんない。
こんな↓感じで、なんか部分的にしかソートしてくれないみたい。
http://dpaste.org/ri4On/ バグ?
理由を知ってる人がいたら教えてちょうだい。
環境: 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
まぁ、ls -Sで良いんじゃないのか
>>784 > 理由を知ってる人がいたら教えてちょうだい。
使い方が間違っている。
0番目から数えたくなる気持は分からなくもない
いや、だって、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ならソートしてくれたよ。 なんだかスレ汚し失礼しました。
本当だ。普段manpageは英語のものしか見ないから気付かなかった。
俺もだまされた。 さすが Linux とおもた。
Linuxの日本語manはまったく整備されてないからなぁ
alias man='LANG=C man' しとくのオススメ
$ man sort じゃなくて $ info sort がオヌヌメ
コマンド foo と同名の関数 foo を作成し、後者の中から前者を呼び出そうと思っています。 function foo { foo } しかし当然ながら無限ループになります。 解決策としては function foo { `which foo` } という方法があります。 しかし毎回 which コマンドを起動するのがちょっと気にかかります。 別の方法として function foo { ¥foo } というのを試しましたが、だめでした。¥foo はエイリアスには効くけど関数にはききませんでした。 というわけで、今のところ which コマンドを使う方法しかなさそうですが、もっといい方法があれば教えて下さい。
>>796 function foo {
command foo
}
そのための「command」コマンド。
話は変わるけど、bashには`help'という組み込み関数があって、 bash$ help function とか bash$ help command とかするとその部分の説明文だけ表示してくれる
単に /usr/bin/foo とかすればいいんじゃないの?
>>799 最適解(
>>797 )が既に出てるのに、外した回答するオマエは黙ってろ。
PATHが違ったら適応できないだろw
>>799 のレスは別に問題視するようなものじゃない。
〜の方が良いと書いてあれば別だが。
>>801 >>796 の質問で、わざわざ `which foo` と書いてることから、
絶対PATHで書いたのでは問題の解決にならないことは読みとれる。
質問者自信も絶対PATHを使う方法は知っている(けどそれじゃ駄目)と読みとれる。
質問の回答になってないのだから問題視されてもしょうがない。
>>797 「command」なんて初めて知りました。完璧です。ありがとうございました。
>>802 状況としてはまったくそのとおりで、すばらしいエスパーっぷりですが、
799はそこまで敵視されるようなことを書いてるわけじゃないので、
そんなに怖がらせなくてもいいかなと思いました。
技術者同士はみんな仲良くね!戦うべき相手は別にいるよ!
>>800 は常駐さんのお決まりレスです。
彼なりにイカしたレスだとお考えになっているのでしょう。
しばらくここにいれば慣れます。
806 :
名無しさん :2012/04/23(月) 01:47:23.08
検索コンプレックス
関数もexportできるようにならないかなぁ 環境変数ならぬ環境関数みたいな 便利だと思うんだけど
>>807 え? できるけど。
export -f
____ / \ / _ノ ヽ、_ \ / o゚⌒ ⌒゚o \ 不毛な言い争いがまた始まるお… | (__人__) | \ ` ⌒´ /
キミの好物じゃないの
>>808 ほんとだ、bashだとexport -fでできるのね
zshだと駄目なんだけどオプションが違うんだろうか
zshは今誰も使ってないからバグが放置されてるんじゃないか?
>>813 そうなんだぁ・・・
いっそbashに戻ろうかな
質問です。 複数のコマンドの実行結果をソートしたいですが、うまくいきません。例えば、 イメージ的には以下のような感じ。 { 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 のファイルに結果がすべて出力されず尻切れになり ます。
zshかbash系だとして一行で済ますなら $ cat <(find PATH1) <(find PATH2) <(find PATH3) | sort $ cat < FILE_A | sort > FILE_A が失敗するのはまあそんなものだと思っておけばいい。 同じファイルから読み込んで出力するのは失敗する。 $ cat < FILE_A | sort > FILE_B ならおk
817 :
名無しさん@お腹いっぱい。 :2012/05/06(日) 04:09:18.13
(rm FILE_A; sort > FILE_A) < FILE_A みたいな手もあるが、間違えたら泣ける。
同じ条件で検索するなら find PATH1 PATH2 PATH3 | sort でいいよな。
>>815 > cat FILE_A | sort > FILE_A
マルチタスクな OS では普通パイプやリダイレクトの際に前後の
プロセスが同時に起動する。
ファイルを読むプロセスが終了するのを待ってファイルを書くプ
ロセスが起動する訳ではない。
なので、上記の場合は最後に書き込むファイル名を変更しなければならない。
TEMP=`tempfile` cat FILE_A > "$TEMP" find PATH1 -print >> "$TEMP" find PATH2 -print >> "$TEMP" find PATH3 -print >> "$TEMP" sort "$TEMP" > FILE_A
すみませんが添付ファイルは梨の奉公でお願いします
>>822 catとパイプが無駄です。
sort -o FILE_A FILE_A
ランダルシュワルツの不要なcat添削を思いだした
添付ファイルを使わないのは大手SIerじゃ常識だね。
思案パイプ
対話方式にならないようにシェルスクリプト自信がroot権限で実行されるようにするスクリプトって作れますか?
>>828 対話的コマンドでもexpectでなんとかなる
>>829 そういう意味じゃなくて、シェルスクリプト中で su -c hoge とかしないで
root権限の動作をさせたいという質問かとエスパー。
基本的にsuidはシェルスクリプトでは許可されてないからねえ。 昔あったsuidperlみたいなののbash版を探してみたけどないみたいだし。 sudersに対象となるスクリプトに対してNOPASSWDを設定するぐらいしか思いつかないや。
>>828 できます
コマンドラインを実行するだけのプログラムを作って
setuidするば
-x 付けて実行してどこでエラーか見てみたら bash -x secrets.sh
837 :
835 :2012/05/09(水) 13:30:45.77
あ、スレ間違えてたorz
なぜかしら、回答としては合ってる気がするぞw
コピペの際に文の末尾に\rが入っちゃってるとか。
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ですが)に書き換えてもらえないでしょうか。
function bd { dirstack[10]=`pwd` \cd ${dirstack[0]} local i for i in 0 1 2 3 4 5 6 7 8 9 ; do dirstack[$i]=${dirstack[$i+1]} done pwd } function nd { dirstack[10]=`pwd` \cd ${dirstack[9]} local i for i in 8 7 6 5 4 3 2 1 0 ; do dirstack[$i+1]=${dirstack[$i]} done dirstack[0]=${dirstack[10]} pwd }
pushd じゃダメなん?
もっとマシな方法ありますか?考えても、これくらいしか思いつかない。 デフォルトのBourne Shellではチルダ展開がないようなので、posix shellにて チルダ展開が必要な場合がある、ファイル名に空白等を含んだものが、パラメータに入っているとして、 file_name="~/src/te st" echo "${file_name}をチルダ展開しlsします。\n" ls -l "$( eval echo -n ${file_name} )"
lsに限らず、それ以外でも扱える、方法が知りたいです。
>>844 例が悪い。その1番下の行の
ls -l "$( eval echo -n ${file_name} )"
だって、複数の空白が空白1個にまとめられちゃうし、
$ < > 等の記号が含まれると ${file_name} (クォートなし)の展開と
evalの展開で大変なことになるぞ。
>>846 確かに、例は悪いだろうな。大変なことになる。
でも考えても、これくらいしか思いつかなかったので、
いい加減にして、聞いた方が早いかと書き込んだんだよ。
シェル変数内にチルダが入っている時、チルダ展開だけやって その他の空白とか * $ < > とかの解釈はさせないって方法がないんだよな。 sedでチルダを $HOME に書き換えろ。
>>844 file_name="~/src/te st * $ < >"
ls -l "${file_name/\~/$HOME}"
>>846 ,
>>848 ,
>>849 あああ!ありがとう。
ls -l "$( echo -n "${file_name}" | sed s#^~#$HOME# )"
851 :
844 :2012/05/16(水) 21:00:34.05
しばらく考えてこうしました。 ls -l "$( [ "${file_name%%/*}" = "~" ] && echo "$HOME/${file_name#~/}" || echo "${file_name}" )" if [ "${file_name%%/*}" = "~" ] then ls -l "$HOME/${file_name#~/}" else ls -l "${file_name}" fi
852 :
名無しさん@お腹いっぱい。 :2012/05/18(金) 05:23:42.76
v7shについて色々調べてるのですがどうしても関数を使用しようとすると test.sh: syntax error at line 2: `(' unexpected とエラーが出てきて使用できません。空白、頭にfunctionを付ける等いろいろ試してみましたがやはり変わらず・・・ UNIX version 7の頃のshには関数がないということでしょうか?
sage忘れました。申し訳ないです。
>>852 シェル関数はないよ。
代用として、シェル関数にしたい内容をシェル変数に入れて、その変数を実行する。
func='ls -l'
$func
で ls -l が実行される。引数を渡したい時は工夫して。
>>852 あんまり役に立たないかも知れないですが、無いと思います。
参考までに
1. Bourne Shell Tutorial
http://www.grymoire.com/Unix/Sh.html The original version of the Bourne shell didn't have functions. If you wanted to perform an operation more than once, you either had to duplicate the code, or create a new shell script.
2. Linux におけるシェルの進化
http://www.ibm.com/developerworks/jp/linux/library/l-linux-shells/?cmp=dw&cpb=dwlin&ct=dwrss&cr=dwrss&ccy=jp&csr=012012 ただし、関数を定義する機能は欠けていました。
3. 知っている限りでは、ここが一番情報が多い
traditional Bourne shell family / history and development
http://www.in-ulm.de/~mascheck/bourne/ The Variants
A summary of the most important changes
? Version 7 (1979) control structures, cmd substitution, () and {}, arbitrary variable names, trap, eval, special parameter substitutions, case
? System III (1981) #, [!...], colon parameter substitution, set --
? SVR1 (1983) shift n
? SVR2 (1984) functions, built-ins: unset echo type, redirection for builtins
4. 3の下の方のSource codeにある、Nikola Vladov のマニュアルで、
man v7sh
BUGS Coexists with but doesn't understand shell functions.
5. FreeBSD Portsはよく分かりませんが、
v7sh FreeBSD
http://www.freebsdsoftware.org/shells/v7sh.html functions aren't supported and command line input is not 8 bit clean
>>854 >>855 ありがとうございます!やっぱりなかったんですね
case文で;;を使用してもcase文抜けられないのも仕様なのかなぁ
マニュアル読んだら使用できそうではあったんですけども・・・一応使用したテストスクリプト上げておきます。
#!/usr/local/bin/v7sh
case $1 in
a)
echo "A!!"
;;
b)
echo "B!!"
;;
c|d)
echo "C or D"
;;
[e-h])
echo "E kara H"
;;
*)
echo "NANIKORE?"
;;
esac
で結果が以下のようになりました。
$ test.sh a
A!!
NANIKORE?
仕様じゃね? ソースあるんだから読んで解析してくれ 読みにくいってレベルじゃないけど
>>856 なんででしょうね?
そのままコピペしてv7shで試しましたが、こちらでは期待通りの動作でした。
$ ./v7case.sh a
A!!
$
>>858 謎ですね・・・v7shなんて過去のものですから大差があるとは考えにくいですし
通常のコマンド待ち状態で ;; を打つとエラーが出ますから
case内でしか特殊な意味を持たないと思われるんですけどね・・・
msysgit(windows版git)付属のbashでログイン時のディレクトリをホーム以外にしたいんだけど、どうしたらいい? 例えば、$HOME/work/hogeでいつも作業するのでbash起動時にそこにいて欲しい。 $HOMEを書きかえると他にも影響があり過ぎるので別の方法教えてください。 適切なスレが見つからなかったので、誘導して。
etc/profileの最後にcd ~/work/hoge?
そんな単純なことでよかったのか... 恥ずかしいー
$HOME/.bash_profileの方が良いんじゃ?
かなり遅れましたが
>>834 です
-xをつけて実行してみたところ、
# bash -x secrets.sh
+ echo -n
: Invalid argument: apks.txt
+ echo -n
: Invalid argument: output.txt
secrets.sh: line 5: syntax error near unexpected toke' `do
'ecrets.sh: line 5: `do
以下のようになりました。
839は読んだの? hexdump -C secrets.sh | head したら、0d 0aになってる所あるんじゃないの?
>>865 0d が付いていたとしても
>>864 の Invalid argument: のエラーにはならないから、その問題じゃないな。
>のopenかwriteのエラーだろうから、 Invalid argumentの理由はシステム依存だろうな。
>>866 FATとかのファイルシステムに echo > 'hoge.txt^M' すると、
: Invalid argument
って出るよ。
とりあえず 違うパーティションに移して実行してみました。 # bash -x secrets.sh + echo -n + echo -n secrets.sh: line 5: syntax error near unexpected toke' `do 'ecrets.sh: line 5: `do
上の議論読んでないのかよ。 0d を消せと。
>>869 だから、
>>865 が言うように行末に(見えない) ^M (0d) が付いてるのが原因だって。
for hoge in hoge^M
do^M
みたいになってて、forの行では ^M がそういう文字として解釈されるから
一応エラーは出ないけど、次の do の行で、doの代わりに do^M が書いてあるから、
syntax error near unexpected token `do^M'
と出る。^Mはカーソル移動を伴うから、`do^M' の表示が乱れて
toke' `do みたいにおかしく表示されているのも説明が付く。
>>871 do^Mとは
書いてありませんでした。
コピペしてるので写し間違いはないはずです。
もうほっとけ。
\rを全部消して実行してみました。 # bash -x secrets.sh secrets.sh: line 2: syntax error near unexpected token `do' secrets.sh: line 2: `do bin2xml $x.folder/AndroidManifest.xml > $x.folder/AndroidManifest.decoded.xmldonefor x in `find . -name "AndroidManifest.decoded.xml"`do echo "$x:" >> output.txt cat $x | grep -i host | sed 's/android:host=\"/*#*#/' | sed 's/\" \/>/#*#*/' | sed 's/\t\t\t\t\t//' >> output.txtdone'
>>874 改行まで消すなよ。
bin2xmlの行が2行目に来てるし、、
よく分からないんでとりあえずhexdumpの結果上げます。 # hexdump -c secrets.sh | head 0000000 # ! / b i n / b a s h \r \n e c h 0000010 o - n > a p k s . t x t \r 0000020 \n e c h o - n > o u t p u 0000030 t . t x t \r \n f o r x i n 0000040 ` f i n d . - n a m e " * 0000050 . a p k " ` \r \n d o \r \n \t u n z 0000060 i p - p $ x | s t r i n 0000070 g s | g r e p - i " a n 0000080 d r o i d . p r o v i d e r . T 0000090 e l e p h o n y . S E C R E T _
大文字小文字の区別はつかないわ、 コマンド行のコピペのまともに出来ない人間が、 xda-developers.comなんかに手を出さないほうがいいよ。 コンピュータは向いてない。
utf16じゃ実行できないんじゃね?
ANSIです。 それと簡単なシェルスクリプトを動かしたら似たようなエラーが発生しました。 # bash test.sh aaa : command not found : command not found test.sh: line 12: syntax error near unexpected token `fi' test.sh: line 12: `fi'
>>879 >>876 が発狂する前に hexdump -C secrets.sh | head の出力を貼ってください
-cじゃなくて-Cでお願いします
881 :
880 :2012/05/25(金) 18:30:52.81
もう俺の中では結論出てるよ。 原因は出てる通り CR で、CR取れと指示されたら CRを知らない質問者が CR LFともに取って1行にしただけ。 エラーメッセージからも裏付けられる。
hexdump -C secrets.sh 00000000 23 21 2f 62 69 6e 2f 62 61 73 68 0d 0a 65 63 68 |#!/bin/bash..ech| 00000010 6f 20 2d 6e 20 3e 20 61 70 6b 73 2e 74 78 74 0d |o -n > apks.txt.| 00000020 0a 65 63 68 6f 20 2d 6e 20 3e 20 6f 75 74 70 75 |.echo -n > outpu| 00000030 74 2e 74 78 74 0d 0a 66 6f 72 20 78 20 69 6e 20 |t.txt..for x in | 00000040 60 66 69 6e 64 20 2e 20 2d 6e 61 6d 65 20 22 2a |`find . -name "*| 00000050 2e 61 70 6b 22 60 0d 0a 64 6f 0d 0a 09 75 6e 7a |.apk"`..do...unz| 00000060 69 70 20 2d 70 20 24 78 20 7c 20 73 74 72 69 6e |ip -p $x | strin| 00000070 67 73 20 7c 20 67 72 65 70 20 2d 69 20 22 61 6e |gs | grep -i "an| 00000080 64 72 6f 69 64 2e 70 72 6f 76 69 64 65 72 2e 54 |droid.provider.T| 00000090 65 6c 65 70 68 6f 6e 79 2e 53 45 43 52 45 54 5f |elephony.SECRET_| 000000a0 43 4f 44 45 22 0d 0a 09 69 66 20 5b 20 24 3f 20 |CODE"...if [ $? | 000000b0 2d 65 71 20 30 20 5d 3b 20 74 68 65 6e 0d 0a 09 |-eq 0 ]; then...| 000000c0 09 65 63 68 6f 20 24 78 20 3e 3e 20 61 70 6b 73 |.echo $x >> apks| 000000d0 2e 74 78 74 0d 0a 09 66 69 0d 0a 64 6f 6e 65 0d |.txt...fi..done.| 000000e0 0a 66 6f 72 20 78 20 69 6e 20 60 63 61 74 20 61 |.for x in `cat a| 000000f0 70 6b 73 2e 74 78 74 60 0d 0a 64 6f 0d 0a 09 6d |pks.txt`..do...m| 00000100 6b 64 69 72 20 22 24 78 2e 66 6f 6c 64 65 72 22 |kdir "$x.folder"| 00000110 0d 0a 09 6d 76 20 24 78 20 24 78 2e 66 6f 6c 64 |...mv $x $x.fold| 00000120 65 72 0d 0a 64 6f 6e 65 0d 0a 66 6f 72 20 78 20 |er..done..for x | 00000130 69 6e 20 60 63 61 74 20 61 70 6b 73 2e 74 78 74 |in `cat apks.txt| 00000140 60 0d 0a 64 6f 0d 0a 09 75 6e 7a 69 70 20 2d 64 |`..do...unzip -d| 00000150 20 24 78 2e 66 6f 6c 64 65 72 20 24 78 2e 66 6f | $x.folder $x.fo|
>>882 ありがとうございます。
まさにその通りでした。
一応走り出したんですが
# bash secrets.sh
unzip: can't open as, as.zip, as.ZIP
unzip: can't open an, an.zip, an.ZIP
unzip: can't open Droid.apk, Droid.apk.zip, Droid.apk.ZIP
unzip: zip flags 1 and 8 are not supported
unzip: zip flags 1 and 8 are not supported
unzip: zip flags 1 and 8 are not supported
unzip: zip flags 1 and 8 are not supported
unzip: zip flags 1 and 8 are not supported
unzip: zip flags 1 and 8 are not supported
unzip: can't open as, as.zip, as.ZIP
unzip: can't open an, an.zip, an.ZIP
unzip: can't open Droid.apk, Droid.apk.zip, Droid.apk.ZIP
とエラーを延々と吐かれました。
このスレに必要もないzip拡張子付ける糞unzipはいるかー!? cygwinのまともなunzipはどこかにおらんかー!?
find "${DIR}/" -prune -name '*.png' -printf "$(tput bold; tput setaf 1) %f $(tput sgr0)" find "${DIR}/A/" -name '*.png' -printf "$(tput bold; tput setaf 6) %f $(tput sgr0)" find "${DIR}/B/" -name '*.png' -printf "$(tput bold; tput setaf 5) %f $(tput sgr0)" find "${DIR2}/" -prune -name '*.png' -printf "$(tput bold; tput setaf 5) %f $(tput sgr0)" とあるディレクトリ内にある画像ファイルをディレクトリ別に色違いで表示させたいです。 似たような単作業なのでどうにかこれを簡略化したいのですが、どうすればいいでしょうか?
>>886 -pathオプションを使う。
find "$DIR" "$DIR2" \
\( -path "$DIR/A/*.png" -printf "$(tput bold; tput setaf 6) %f $(tput sgr0)" \) \
-o \( -path "$DIR/B/*.png" -printf "$(tput bold; tput setaf 5) %f $(tput sgr0)" \) \
-o \( -path "$DIR/*.png" -printf "$(tput bold; tput setaf 1) %f $(tput sgr0)" \) \
-o \( -path "$DIR2/*.png" -printf "$(tput bold; tput setaf 5) %f $(tput sgr0)" \)
OR条件の判断上、-path "$DIR/A/*.png" 等を -path "$DIR/*.png" よりも先にすること。
>>887 どうせなら最初と最後にtputをまとめればもう少し簡単に
tput bold
find "$DIR" "$DIR2" \
\( -path "$DIR/A/*.png" -printf "$(tput setaf 6) %f " \) \
-o \( -path "$DIR/B/*.png" -printf "$(tput setaf 5) %f " \) \
-o \( -path "$DIR/*.png" -printf "$(tput setaf 1) %f " \) \
-o \( -path "$DIR2/*.png" -printf "$(tput setaf 5) %f " \)
tput sgr0
教えてください。 シェルスクリプトに echo cmd とかいて有った場合、そのコマンドが実行される条件って有るのでしょうか? sh /etc/weekly.local とやると、weekly.local内の #!/bin/sh - cd / echo ""; echo "Rebuilding locate database:" echo /usr/libexec/locate.updatedb | nice -5 su -m nobody 2>/dev/null が実行されますが、 vi hoge.sh #!/bin/sh cd / echo /usr/bin/ls と書いて、実行権限も付けた後、 sh hoge.shとやっても /usr/bin/ls としか表示されませんでした。 lsが実行される事を期待したのですが...
>>889 echoの出力をパイプで suに食わせているから結果的に echoの内容が実行される。
同じことをやりたいなら、
echo /usr/bin/ls | sh
だな。
ところでlsが/usr/binにあるって、、Solarisかよ。
ヒアドキュメントの有効な使い方がよくわからない… 探してもcatでの例しかない どなたか有効な使い方教えてくれませんか?
ヒアドキュメントは過去の遺物です。
>>893 過去の使い方でもいいので出来れば教えていただけませんか?
>>892 xmodmap を実行するのにファイルを用意せずに実行する例。
xmodmap - <<EOF
remove Lock = Caps_Lock
remove Control = Control_L
keysym Control_L = Caps_Lock
keysym Caps_Lock = Control_L
add Lock = Caps_Lock
add Control = Control_L
EOF
>>895 それは echoでできるので、ヒアドキュメントの有効な使い方じゃないですね。
echo 'remove Lock = Caps_Lock
remove Control = Control_L
keysym Control_L = Caps_Lock
keysym Caps_Lock = Control_L
add Lock = Caps_Lock
add Control = Control_L' | xmodmap -
そりゃそうだ。 結局のところ標準入力にデータを流しこむ手段のひとつでしかないんだから、 基本的に echo や cat と変わらん。 「それは echo でできる」と言うのならぜんぶ echo でやればいいんじゃねーの? ↓は動かないけど、 date +'%Y %m %d' | read y m d ヒアドキュメントを使った↓は動く。 read y m d<<eod `date +'%Y %m %d'` eod 違いなんてこの程度のものだ。 # ksh は前者も動く。
>>897 それはヒヤドキュよりもeval使った方が簡単だな。
eval `date +'y=%Y m=%m d=%d'`
そういう話はしてないっしょ。
TEMPに書けない環境でヒアドキュメントを使ったら動かなかった。
わざわざ別ファイルにする必要がない程度のリストとかエスケープ面倒な時とか便利。 大昔のUNIX プログラミング環境って本にはそんな感じで書いてあった記憶が。カーニハンとロブパイクのやつね。
ピコーン
ヒアドキュメントの使い方で、こんなの思い出した。 複数のスクリプトをひとまとめにして、メールで送る。受け取った側で実行すると複数のファイルの出来上がり。 cat <<EOF >file1 hogehoge hogehoge EOF cat <<EOF >file2 fugafuga fugafuga EOF
sharか。
こんなのもありますが...
>>897 、
>>901 で話がつきる様な気がします。
クォートを考える必要がある場合、パイプを避ける場合ですね。
ftp << EOF
yum install $1 << CONFIRM
wall <<
vi <<
一時ファイル作りますから完成時には消しますが、ブロックコメントは便利です。
: <<'#COMMENTBLOCK'
あと
exec 3<<EOF
`${command}`
EOF
としておいて、別のところで
while read line; do; done 0<&3 3<&-
>>900 ですよね。
sh -c 'lsof -a -p $$ -d0' << EOF
データベースの操作とかでよく使うな。 変数の展開はしてくれるんで、別ファイルにするより便利な場面は多々ある。
sharが来た!
charじゃなくて?
pidfile=${PIDFILE-/var/run/example.pid} 初めて見た書式なんだけどこれってどういう意味なんです?
>>910 変数PIDFILEを展開するが、もしセットされてなかった場合はデフォルトとして /var/run/example.pid を用いる。
それを pidfileという変数に代入している。
>>910 $ PAGER='less -p:-' man sh
ちゃんと man に書いてはあるんだけど、
${parameter-word} そのものについては書いてなくて、
${parameter:-word} の説明とはちょっと離れたところに
: を省略した場合の動作が書いてあるんだよな。すげー探しづらい。
915 :
905 :2012/05/29(火) 20:59:15.91
訂正。 while read line; do; done 0<&3 3<&- でなく、 while read line; do; done 0<&3 exec 3<&-
記号を使った構文はぐぐりにくいしmanでも探しづらい。
昔はGoogleもある程度の記号が検索できたのに 今はステマ用の単語でしか検索できない。
質問させてください。 以下のような文字列があります。 文字列を見ていき、文字「@」のある無しを配列に入れていきたいのですが、何かいい方法はないでしょうか。 ・文字列 「△@△@△@△@△@△△@△」 空白(△)は文字「@」の前後に一つずつ入っています。 ただし、稀に連続で出現する場合があります。 ?バイト目での「@」の出現有無を配列に格納したいです。 set -A ARRY △@△@△@△@△@△△@△ echo ${ARRY[11]}の結果で△を返したいのですが、 思い通りになりません。。。 シェルはkshです。よろしくお願いします。
質問です。 あるシェルスクリプトの中に、 rm -rf -- *; という一文が有ったのですが、 --はどういう意味が有るのでしょうか?
>>919 -で始まるファイルも消すためのオプション
>>919 正確にはオプションの終わりを明示する為のものなんだけど、rmの場合は*が展開された時に-から始まるファイル名をオプションと認識しないことになるから、
>>920 のようにはたらく。
起動スクリプトを書いています バックグラウンドで実行させる為に以下のように書きましたが service prog start で待機状態?になってしまいうまくいきません daemon --pidfile=${pidfile} ${prog} ${conf} & このようなケースではどういう風に書けばよいのでしょうか?
>>922 daemon(シェル関数) 通す場合は & は要らん。
& なしで勝手に(制御端末切り離して)バックグラウンドになる。
逆に & 付けると動作がおかしくなるかも。
>>923 むむむ、それが&を抜いても制御が戻らないんです…
んー、なんでだろう
>>918 いまいち言ってる事が分からないが、こんな事ですか?
その2で、sed使わないで置換できたら面白かったけど。2ch仕様の為、空白を・にしてます。
#!/bin/ksh
strings="${1:-・@・@・@・@・@・・@・}"
function・kekka・{
・・・for・((・n・=・0;・n・<・${#ARRY[@]};・n++・))・;・do
・・・・・・echo・-n・"配列${n}=${ARRY[$n]}・"
・・・done
・・・echo
}
#その1
for・((・n・=・0;・n・<・"${#strings}";・n++・))・;・do
・・・ARRY[$n]="${strings:$n:1}"
done
kekka;・echo
#その2
bufIFS=${IFS};・IFS=,
set・-A・ARRY・$(・echo・"${strings}"・|・sed・-e・'s/./&,/g'・)
IFS=${bufIFS}
kekka
928 :
927 :2012/05/30(水) 19:17:37.42
bufIFS=${IFS}; IFS=, set -A ARRY ${strings//?/${.sh.match[0]},} IFS=${bufIFS}
931 :
927 :2012/05/30(水) 22:47:57.45
((・n・
>>928 みたいな、replace w/ back reference on expansion timeなものは、
bash様で書けるのかと聞きたい。
+・)) kshすてき?
932 :
918 :2012/05/30(水) 23:16:46.44
>>927 それです!今試したらやりたいことが出来ました。
初見の機能ばかりで、いまいち詳細はよくわかってませんが^^;
シェルを見ながら使い方を覚えてみます。ありがとうございました。
教えてください。 (cd $HOME/makedir; make) の()は前後に空白を入れたり、;を最後のコマンドに入れたりしなくていいそうです。 { command1; command2; .....; } の{}は前後に空白を入れなければならないし、;を最後に入れないと行けないそうです。 なんででしょうか?
厳密にはコマンドじゃないけどな。 type { してみ。
コマンドだった・・・
だよな。/bin/{ があるので、間違って消してはいけない。
ウッソだぁ〜
939 :
933 :2012/05/31(木) 22:58:07.09
type type } } is a shell keyword type [ [ is a shell builtin と出ました。 { } がコマンドに近いもので、 ()が文法に近いものという事はわかったのですが、 shell keywordとshell builtinって何が違うのでしょうか?
shell builtin はシェル内部のコマンド。 コマンドだから行末もしくは ; の前までで一区切り。 shell keyword は行末とか ; を越えて働く。
941 :
934 :2012/06/01(金) 07:49:01.20
>>939 かわいそうになって来た。
これ読んでこい。
bash.cyberciti.biz/guide/Shell_commands
>>939 >>941 リンク切れてた
tldp.org/LDP/abs/html/internal.html
shの-kオプションって説明読んだだけでは分からないんだけども どういった動きをするんですかね?
>>943 printenv HOGE HOGE=boke
みたいなことができる。
$ printenv HOGE HOGE=boke $ set -k $ printenv HOGE HOGE=boke boke
で、どういった動きをするんですかね?
マニュアルが読めないやつと文章が書けないやつの筆談ってこうなるのか
$ sh -k Illegal option -k
-k って初めて知ったけど ksh からの拡張なのか。 これがあるとどんなときに嬉しいんだろ? awk -v var=value ... というコマンドが実行できなくなるとか デメリットしか思い浮かばないんだけど。 HOGE=fuga command という構文なんぞいらん、 必要なら env HOGE=fuga command でいいじゃねーか、と思ってるぐらいなのに、 さらに拡張する意義がさっぱりわからん。
>>944 で分からないなら、新しいスクリプトでの使用が(少なくともkshでは)非推奨だそうだから使わなくていいが、
1. まず、マニュアルを見る。もし環境変数について分からなければ、それも調べる。
bashで分からなければ、kshのマニュアルが分かりやすい。
http://uw714doc.sco.com/ja/man/html.1/ksh.1.html > 旧式の -k オプションが設定されていると、....
2. set -k と、 set +k について試す。
$ echo a=b c
$ sh -c a=UNIX 'echo $a MAGAZINE'
>> 950 少なくとも、UNIX Version 7 の Bourne からあるようだ。Thompson shellは-t -cのみ。
http://www.tuhs.org/ >> 949 の sh は、Bourne Shell でなく、ash か dash じゃないか?
学校の課題でシェルスクリプトの作成、及び 既存のシェルスクリプトの動作内容の説明が課題になっているのですが 習い始めでコマンドすらまともに分からない状態なので、何が何やらさっぱりです PCすらそんな使わないので、マニュアルみながらでも頭が弾けそうです・・ ここで質問すれば答えてもらえるでしょうか?殆ど丸投げになりそうですが。。 時間があれば1つ1つ学びながら進めたいんですが、何せ時間がないもんで;;
死ね
ヤフー知恵なんたらとか教えてグーとかにでも丸投げしておけば お節介な誰かが課題解いてくれるっしょ
学校の課題って言わずに、丸投げって気づかれないように適当に質問すればすぐに答が返ってくるのに...
>>955 いや
>>939 辺りからの流れ見てると
その答えが自分には答えになって無いほど難しく
自分の無知さで質問したら怒られそうだったので・・
前置きはいいからさっさと質問すれ
958 :
749 :2012/06/06(水) 23:29:09.32
>>956 とりあえず投げれば暇な奴が氏ねとかググれカスとかman読めとか言いながらも答えてくれんじゃね?
以下の動作を行うシェルスクリプトを作成しなさい。 report6.tex から report6.dvi を作成する. report6.dvi から report6.pdf を作成する. xdvi により report6.dvi の内容を表示する. report6.tex, report6.dvi, report6.pdfの各ファイルサイズを出力する。 というものです;;まだまだ動作説明とか沢山あるのに オンラインマニュアルを参照しつつ3時間ほど悪戦苦闘しましたが 1つも進まず、正直泣きたい気分です。。。 既存のシェルは文長くなりすぎて書き込めませんが
そこは普通はシェルスクリプトじゃなくて makeかomakeあたりで書くところだろという突っ込みはなし?
platex report6.tex dvipdfmx report6.dvi xdvi report6.dvi wc -c report6.tex, report6.dvi, report6.pdf
志村ーカンマー
>>961 本当にありがとう御座います。
それだけの物でもマニャアル読みながらだと中々書けない
以下の様なスクリプトの動作説明が8つぐらいあるのすが
#!/bin/sh
# remember - an easy command-line based memory pad
# search the results with 'remindme'
rememberfile="$HOME/.remember"
if [ $# -eq 0 ] ; then
echo "Enter note, end with ^D "
#ヒント:下記の cat の入力は標準入力です。入力の終了は空行で ^D を押します
cat - >> $rememberfile
else
echo "$@" >> $rememberfile
fi
人に聞かずにやるには限界です。。1歩も前に進まない。。
964 :
749 :2012/06/07(木) 00:26:41.76
>>963 動作説明ってこんな感じでいいのか?
>#!/bin/sh
>
># remember - an easy command-line based memory pad
># search the results with 'remindme'
>
>rememberfile="$HOME/.remember"
ファイル指定
>
>if [ $# -eq 0 ] ; then
引数がなければ
>echo "Enter note, end with ^D "
""内の文字列を表示
>#ヒント:下記の cat の入力は標準入力です。入力の終了は空行で ^D を押します
>cat - >> $rememberfile
キー入力を$HOME/.rememberに書き込み
>else
引数があれば
>echo "$@" >> $rememberfile
引数全体を$HOME/.rememberに書き込み
>fi
>>964 正にその通りです。後4つが分かれば残りはそれらを参照すれば出来るそうですのでお願いします.
#!/bin/sh
# formatdir - output a directory listing
for file in *
do
if [ -d "$file" ]
then
size=`ls -1 "$file" | wc -l | sed 's/ //g'`
if [ $size -eq 1 ]
then
echo "$file ($size entry)"
else
echo "$file ($size entries)"
fi
else
size=`ls -l "$file" | sed 's/^[^ ]*[ ]*[^ ]*[ ]*[^ ]*[ ]*[^ ]*[ ]*\([0-9]*\)[^0-9].*/\1/'`
echo "$file ($size byte)"
fi
done
#!/bin/sh # checkspelling - check the spelling of a word spell="ispell -l" # if you have ispell installed instead # if not, just define spell=spell or # equivalent. # ヒント # "ispell -l" は標準入力から入力された単語(複数)から # スペルの間違っている単語だけを出力します。 if [ $# -lt 1 ] ; then echo "Usage: $0 word or words" >&2 exit 1 fi for word in $* do test=`echo $word | $spell` if [ -z "$test" ] ; then echo "$word: spelled correctly." else echo "$word: misspelled." fi done
#!/bin/sh # hilow - a simple number guessing game biggest=100 # maximum number possible guess=0 # guessed by player guesses=0 # number of guesses made number=`expr $$ % $biggest` # 1 から $biggest の間の乱数を生成 while [ $guess -ne $number ] do echo "Guess? " read guess # read guess で guess 変数にキーボードから入力した値が入る if [ $guess -lt $number ] then echo "... bigger!" elif [ $guess -gt $number ] then echo "... smaller!" fi guesses=`expr $guesses + 1` # guesses の値を1増やしている done echo "Right!! Guessed $number in $guesses guesses."
#!/bin/sh # remindme - search a datafile for matching lines, or show the contents # of the datafile if no arg is specified rememberfile="$HOME/.remember" if [ $# -eq 0 ] ; then less $rememberfile else grep -i "$@" $rememberfile | less fi
>>965 >for file in *
カレントディレクトリ内のすべてのファイル名、ディレクトリ名について繰り返し。fileには作業対象ファイル(ディレクトリ)名が入る。
>do
>if [ -d "$file" ]
$fileがディレクトリなら
>then
>size=`ls -1 "$file" | wc -l | sed 's/ //g'`
ディレクトリ内のファイル数を数える。
>if [ $size -eq 1 ]
ファイル数が1なら
>then
>echo "$file ($size entry)"
単数形で表示
>else
ファイルが複数あれば
>echo "$file ($size entries)"
複数形で表示
>fi
>else
ディレクトリじゃなければ
>size=`ls -l "$file" | sed 's/^[^ ]*[ ]*[^ ]*[ ]*[^ ]*[ ]*[^ ]*[ ]*\([0-9]*\)[^0-9].*/\1/'`
サイズの部分を切り出して
>echo "$file ($size byte)"
表示
>fi
>done
しかし、おまえの勉強にはまったくなってないけど、いいの?
972 :
970 :2012/06/07(木) 01:17:17.49
>>966 >spell="ispell -l" # if you have ispell installed instead
スペルチェックに使うコマンドの指定。
># if not, just define spell=spell or
># equivalent.
>
>if [ $# -lt 1 ] ; then
引数の数が1より小さければ
>echo "Usage: $0 word or words" >&2
標準エラー出力に表示
>exit 1
スクリプト終了、終了コード1
>fi
>
>for word in $*
すべての引数について繰り返し
>do
>test=`echo $word | $spell`
$wordをspellに渡して
>if [ -z "$test" ] ; then
spellの結果が0文字なら
>echo "$word: spelled correctly."
スペルミスしてない
>else
スペルミスがあれば
>echo "$word: misspelled."
スペルミスしてるよ。
>fi
>done
>>971 仰る通りです。。
このままではいけないのでこのような質問の仕方は今回限りにします
>>967 は終わってるのかな。
>>968 >#!/bin/sh
>
># remindme - search a datafile for matching lines, or show the contents
># of the datafile if no arg is specified
>
>rememberfile="$HOME/.remember"
>
>if [ $# -eq 0 ] ; then
引数がなければ
>less $rememberfile
$rememberfileをそのまま表示
>else
引数があれば
>grep -i "$@" $rememberfile | less
引数で検索して表示
>fi
>>970 ホントだ。。。
完全にココのコピペですね;;すげぇ
まぁ動作の解読が必要な事は変わりなさそうですね・・
シェルスクリプト書くならエディタは何がお勧めですか?
vim,emacs
秀丸
どれでもたいして変わらんよ。 使い慣れたエディタで書けばいい。
言い忘れましたがif,for,while,case文などでちゃんとインデントしてくれて 簡単な文法チェックもできるエディタ限定でお願いします
>>979 秀丸使ったことないけど具体的にどんなところがいいの?
vimと比較したいです。
>>982 キーバインドが標準的
文法チェックが出来る
インデントも正しく出来る
標準的ときたか!!
名前とアイコンは標準的じゃないね
標準かどうかはともかくエディタの人口で言うとvimやemacsの方が圧勝だよな 4200円っていう価格設定と実質日本人しか使ってないってのは痛い
そもそもWindowsのキーバインド基準に言われても
母数関係ない話になんでいきなり母数言い出すのか意味不明の頭の悪さ。
現実って何だ?
992 :
970 :2012/06/07(木) 23:46:20.41
>>990 すまん。規制されててスレ立てられんかった。誰か頼む。
だめだった
995 :
970 :2012/06/08(金) 00:40:06.21
秀丸推しはステマだろ。使ってる奴見た事ある人いるの?
埋め
埋め
1000なら 秀丸が標準になる
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。