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

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

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

□前スレや過去スレ:
シェルスクリプト総合 その1
http://pc8.2ch.net/test/read.cgi/unix/1101820646/
☆シェルスクリプトを勉強するにあたって☆
http://pc5.2ch.net/test/read.cgi/unix/989659936/
便利なシェルスクリプト見せろ
http://pc5.2ch.net/test/read.cgi/unix/996949546/
【貝】第1回シェル講座【殻】
http://fun.kz/test/read.cgi/unix/1016372780/

□関連スレ:
sed
http://pc8.2ch.net/test/read.cgi/unix/1085730992/
おまえら! shell は何を使っているんですか?
http://pc5.2ch.net/test/read.cgi/unix/1012330865/
Eshell の使い方とか設定とか【Emacs Shell、Lisp】
http://pc8.2ch.net/test/read.cgi/unix/1102921590/

□他板の関連スレ:
Macでシェルスクリプト総合 Part 1
http://pc7.2ch.net/test/read.cgi/mac/1105074933/
【Shell】どのシェル使ってる?【Script】
http://pc8.2ch.net/test/read.cgi/linux/1067330754/
0745名無しさん@お腹いっぱい。2005/07/26(火) 01:41:35
>>743
そんな調査するより xargs を使うべきじゃないの。
07467432005/07/26(火) 02:21:40
>>744 そうですか、それなら可能ですかね。。。?アドバイスありがとうございます。

>>743 xargsですか。ちょっと知らないコマンドですが、調べてみますね。レス感謝です。
0747名無しさん@お腹いっぱい。2005/07/26(火) 02:21:47
>>743
find /usr/include -name '*.h'|xargs grep ARG_MAX
0748名無しさん@お腹いっぱい。2005/07/26(火) 02:40:21
getconf ARG_MAX
0749名無しさん@お腹いっぱい。2005/07/26(火) 02:46:40
>>743
こういったことの周りの知識を知らないのも問題だが、
知識不足なのにいたずらに限界に挑戦しようとする方も問題。
知識不足なら知識不足なりに秘孔をついてしまわぬよう安全策をとるのが一つの見識。
0750名無しさん@お腹いっぱい。2005/07/26(火) 07:55:30
>>745
確かに xargs -n で引数を分割して実行できるが、
xargsはスペースや改行等を含んだファイル名を
正しく扱えないという、仕様上のバグがあるので、
xargs自体obsolete or deprecated。

xargs -0 (xargs --null)が使えるのはGNU xargsだけなので、
一般には使えないと考えるべき。
0751名無しさん@お腹いっぱい。2005/07/26(火) 09:42:40
逆に、ファイル名に問題あるのが確実にない状況なら十分使える。
でなきゃ GNU の入れりゃいいじゃん。
0752名無しさん@お腹いっぱい。2005/07/26(火) 09:44:18
>>750
だけではない。
0753名無しさん@お腹いっぱい。2005/07/26(火) 09:47:48
>>752
何が?
0754名無しさん@お腹いっぱい。2005/07/26(火) 09:59:11
(xargs -0 (xargs --null)が使えるのはGNU xargs)だけではない。
0755名無しさん@お腹いっぱい。2005/07/26(火) 11:01:49
>>751
「ファイル名に問題ないことが確実」な状況って、
自分の作業用ディレクトリ下で、
書き捨てスクリプトを書く場合くらいしかないぞ。
ユーザー開放のディレクトリ以下を一括処理したい場合、
どういうファイルネームが存在するかの仮定をしちゃいけないし、
GNU物を勝手に入れるのも禁止だから、
結局xargsなんて使えん、のが結論。
0756名無しさん@お腹いっぱい。2005/07/26(火) 11:03:45
>>755
勝手に入れちゃだめならしかるべき手続きを踏めばいいじゃない。
0757名無しさん@お腹いっぱい。2005/07/26(火) 11:11:25
ユーザー開放のディレクトリ以下を一括処理したい、と仮定されました。
0758名無しさん@お腹いっぱい。2005/07/26(火) 12:30:03
まあWindowsユーザは空白含みとか日本語ファイル名は普通に平気で付けるしな
特にSambaサーバにしてるならそういうファイル名は全然珍しくないわな
0759名無しさん@お腹いっぱい。2005/07/26(火) 16:14:40
自分も windows では日本語空白記号なんでも使うな。
0760名無しさん@お腹いっぱい。2005/07/26(火) 16:24:47
そこで、zargs ですよ。
0761名無しさん@お腹いっぱい。2005/07/26(火) 17:55:03
>>750

Solaris 9 だと空白は大丈夫だし、改行も \ でエスケープすれば問題なしですが。

$ /bin/echo 'a b\nc\\\nd' | xargs -L 1 -I '{}' /bin/echo "'{}'"
{a b}
{c
d}
0762名無しさん@お腹いっぱい。2005/07/26(火) 17:56:12
>>761
いまどきSolaris使っている馬鹿ってpupupu−−−
0763名無しさん@お腹いっぱい。2005/07/26(火) 18:23:08
>>762
「Soralis」と書けばよかったのに
0764名無しさん@お腹いっぱい。2005/07/28(木) 08:09:48
>>761

xargsの-L 1オプション使ったら、
1行ごとにコマンド(echo)が実行されてしまうから、
元質問の、「まとめて処理」ができないだろ。

それに、「改行を \ でエスケープ」と言っても、
そう都合良く findで出力できないだろ。

さらに、ファイル名に普通の文字として、
" や ' や \ などが含まれていると
やっぱり駄目だろ。

よって、xargsは使えん。
0765名無しさん@お腹いっぱい。2005/07/28(木) 08:23:23
改行文字がファイル名に含まれてるケースって、そんなにあるか?
基本的にそれは考慮せんでもいいと思うんだが
0766名無しさん@お腹いっぱい。2005/07/28(木) 09:24:00
ファイル名にはヌル文字も使えなかったっけ?
だとしたら xargs -0 も完全な解決策にはならないが。
0767名無しさん@お腹いっぱい。2005/07/28(木) 10:05:15
>>766
ファイル名にnull文字は使えねーよ。
だからxargs -0が最もマトモな解決法なのだが、
Solarisとかで使えないから問題になってるんだよ。
0768名無しさん@お腹いっぱい。2005/07/28(木) 10:10:17
>>765
改行は滅多にないとしても、
ファイル名に ' " \ などが含まれているのは
よくある。
「Don't Cry.mp3」とかね。

xargsが ' " \ を特殊文字扱いするのが問題になる。
0769名無しさん@お腹いっぱい。2005/07/28(木) 11:46:07
>>768
xargsが単純に改行をセパレータとして扱うような
プログラムだったなら、はるかにマシだっただろうね
0770名無しさん@お腹いっぱい。2005/07/28(木) 14:45:33
大学のマシンに xargs が なぜか /usr/local/X11/bin にあったのを思い出した
0771名無しさん@お腹いっぱい。2005/07/28(木) 14:50:42
>770
あっ、そんな記憶ある。
NEWS-OS 4 (3かな?) じゃないかな。
0772名無しさん@お腹いっぱい。2005/07/28(木) 18:31:44
NEWS-OS 4は xargs が付属していないね。
/usr/5binにすらない。
(/usr/5bin/cpioとかならある・・ちなみにunameもない・・)
まあ、xargsは元SysV系ということで、
「使わなくても済むはずのコマンド」の扱いだったのだろう。
07737612005/07/28(木) 19:56:55
>>764

761 で -L 1 を付けたのは、この例だと 1 行ずつ処理しないと
表示が分かりづらいからです。説明が悪かったですね。

改行の入ったファイル名は (find 的に) 無理ですが、
何とかすれば何とかなります。

$ touch "sp ace"
$ touch "single'quote"
$ touch 'double"quote'
$ touch 'back\slash'
$ find . -type f | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/\(.*\)/"\1"/' | xargs /bin/sh -c 'echo "[$1][$2][$3][$4]"' --
[./sp ace][./single'quote][./double"quote][./back\slash]

ま、そこまでして使いたいかと言えば No ですが。
0774名無しさん@お腹いっぱい。2005/07/28(木) 20:27:47
>>771
たしかにマシンのほとんどはNEWSだった。記憶があやふやだったので
local をつけたけど、やはり/usr/X11/binだったのかな
07757712005/07/29(金) 00:50:15
>772, 774
記憶違いだったようで、スミマセン。
ひょっとしたら、初心者の私が
「ファイル名が x で始まるのに、どうして/usr/bin/X11にないんだ」
(笑わないでオクレ!)
と思ったのが記憶に残っていたのかもしない。
あっ、 NEWS-OSの X 関係は /usr/bin|lib/X11というのも違うかも。

近くの席にはSUN 3 が有ったなぁ。
0776名無しさん@お腹いっぱい。2005/07/29(金) 03:39:56
>>772
xargs はあった方が良いと思うんだが。
これの代わりをするには、たくさんコマンド組み合わせてやらないといかん希ガス
0777名無しさん@お腹いっぱい。2005/07/29(金) 08:14:57
よくわからんが775は771ではない。772の間違いかな。ただ、X関係の下に
あったという記憶は同じようだけど。NEWSのキーボードのタッチは好きだった。
「~」の位置のせいで痛いミスをしたことがあったが…

xargsはコマンドライン以外で使ったことがないかもしれん。
0778名無しさん@お腹いっぱい。2005/07/29(金) 08:19:04
>>776
xargsは実行時効率とタイプ量減らすためって気がする

たんに機能の話だけで言えば
cmdA | xargs cmdB

cmdA | while read i; do cmdB $i; done
でいいし(後者は効率が悪いがIFSで適切なデリミタを設定することもできる)
0779名無しさん@お腹いっぱい。2005/07/29(金) 08:28:34
いつまで引っ張る気だ。
0780名無しさん@お腹いっぱい。2005/07/29(金) 10:04:04
771=775 です。
随分昔の話なので、私の記憶が間違っていたのかと思いました。

>777
コマンドライン以外で使うxargs って、スクリプトの中に書くという事ですよね。
それとも、使いやすいGUIが有るとか? (そんなGUI 想像つかない)
# スレ違いなんで、このくらいにしておきます。 orz
0781名無しさん@お腹いっぱい。2005/07/29(金) 18:23:59
argument が無限に取れるシェルがあれば
xarg はいらないの?
0782名無しさん@お腹いっぱい。2005/07/29(金) 18:26:25
シェルが取れてもコマンドが取れなければあまりい意味が無い
0783名無しさん@お腹いっぱい。2005/07/29(金) 18:37:57
でもそれは xargs でも解決できないよね。
0784名無しさん@お腹いっぱい。2005/07/30(土) 09:24:10
>>783
xargs -i cmd {} でほぼ解決できる。
パフォーマンスは知らん。
0785名無しさん@お腹いっぱい。2005/07/30(土) 10:19:58
>>784
だからぁー、-iオプション付けると
-l 1も暗黙に付いちゃうから、xargs使う意味がなくなるんだよ。
解決するのはスペースを区切り文字とみなさないことだけであって、
\ とか ' とか " の問題はそのまま未解決。
0786名無しさん@お腹いっぱい。2005/07/30(土) 10:28:10
>だからぁー、-iオプション付けると
>-l 1も暗黙に付いちゃうから、xargs使う意味がなくなるんだよ。
意味不明。
0787名無しさん@お腹いっぱい。2005/07/30(土) 11:01:57
>>785
何を言ってるんだ?w
0788名無しさん@お腹いっぱい。2005/07/30(土) 14:54:36
多数のファイル名を拡張子を付けたファイル名に変換したいのだがrenameはつかえるのかな?

f1 f2 f3 f4 ->f1.jpg f2.jpg f3.jpg f4.jpg
0789名無しさん@お腹いっぱい。2005/07/30(土) 15:00:30
for file in * ; do
 mv $file $file.jpg
done
0790名無しさん@お腹いっぱい。2005/07/31(日) 21:14:35
>>789
rename って言ってるってことはMS-DOSプロンプトなんだろうよ

正解は >>791 よろしく
0791名無しさん@お腹いっぱい。2005/07/31(日) 21:20:03
ちょっくらうんこいってくる。
0792名無しさん@お腹いっぱい。2005/07/31(日) 21:22:19
DOSプロンプトだったら、rename * *.jpg
0793名無しさん@お腹いっぱい。2005/07/31(日) 21:37:19
Linuxだとrenameというコマンドがディス鳥標準で付いていて、一応使える。
ただし一般的ではない。
>>789
はダブルクォート付けていないから、減点だな。
0794名無しさん@お腹いっぱい。2005/07/31(日) 21:45:25
そもそも >>788 は「多数のファイル名を」って言ってるんだから、
* はまずいだろ
0795名無しさん@お腹いっぱい。2005/07/31(日) 22:00:17
>>788 が言う「多数」は4つくらいのようだ。
0796名無しさん@お腹いっぱい。2005/08/01(月) 08:28:05
zsh 使ってるなら zmv も便利
0797名無しさん@お腹いっぱい。2005/08/02(火) 12:42:06
tailの逆、つまり先頭から(ファイル最終のn行前)まで表示するにはどうすれば
いいでしょう?
0798名無しさん@お腹いっぱい。2005/08/02(火) 12:42:33
head
0799名無しさん@お腹いっぱい。2005/08/02(火) 13:38:30
>>797
tail -r
0800名無しさん@お腹いっぱい。2005/08/02(火) 23:45:18
>>799
ひねくれ者め(笑)
0801名無しさん@お腹いっぱい。2005/08/03(水) 00:25:16
liat
0802名無しさん@お腹いっぱい。2005/08/03(水) 00:56:37
ファイル最終の n 行前までって言ってるんだから、
実際のところ head で実現するのは苦しい気がする。
(head で指定できる行数は限りがあったと思うので。)

てことで
 tail -<n> <file_name> > <tmp_file>
 comm -23 <file_name> <tmp_file>
 rm -f <tmp_file>
かな。
0803名無しさん@お腹いっぱい。2005/08/03(水) 02:44:09
ファイル途中にtmp_fileと同一行が出たらおかしくならないか?
0804名無しさん@お腹いっぱい。2005/08/03(水) 03:14:44
comm はソートされたファイルじゃないと使えない
0805名無しさん@お腹いっぱい。2005/08/03(水) 03:32:44
んな、ファイル丸ごと何度も読み書きするくらいだったら、たとえば
last=100
rows=`wc -l file | cut -d ' ' -f 1`
head -n `expr $rows - $last` file
とか。
0806名無しさん@お腹いっぱい。2005/08/03(水) 03:37:55
wc -l file | cut -d ' ' -f 1

wc -l < file
でいいだろ
0807名無しさん@お腹いっぱい。2005/08/03(水) 07:23:57
>>806
??
0808名無しさん@お腹いっぱい。2005/08/03(水) 10:14:37
tail -r | tail +n | tail -r

GNU tail では -r はないようなのでかわりに tac を。
0809名無しさん@お腹いっぱい。2005/08/03(水) 12:55:11
tail -rだと全文をバッファに抱えるプロセスを二つ重ねないといけないので、
あんまり嬉しくないんですよね。

というわけで、こうかなあと。(n=4の場合)
ruby -ne '(q||=[])<<$_;q.size<=4||print(q.shift)' file
0810名無しさん@お腹いっぱい。2005/08/03(水) 13:07:44
echo '1,$-Np' | ed file
0811名無しさん@お腹いっぱい。2005/08/03(水) 17:21:46
質問させてください。
スクリプトを実行したら
login:
名前を打ち込んで
password:
パスを打ち込む(非表示)
パスはファイルにリダイレクト
っていうのを作りたいんですが。バッシュで。
途中で文字列を入力させるやり方が分かりません。
教えてください。おねがいします。
0812名無しさん@お腹いっぱい。2005/08/03(水) 17:37:23
read -p 'login: ' NAME
read -s -p 'password: ' PASS
echo $PASS > file
0813名無しさん@お腹いっぱい。2005/08/03(水) 20:14:02
そんでそんで? 誰のパス盗もうとしてんの?(σ ̄ー ̄)σ>>811
0814名無しさん@お腹いっぱい。2005/08/04(木) 02:44:04
シェルスクリプトで perl -pe chomp と同じことをしたいのですが、
どのようにやればよいでしょうか?
0815名無しさん@お腹いっぱい。2005/08/04(木) 08:57:48
#!/bin/sh
exec perl -pe chomp
0816名無しさん@お腹いっぱい。2005/08/04(木) 13:31:14
readで出来たのか
知らなかった
0817名無しさん@お腹いっぱい。2005/08/04(木) 13:39:59
 cmd1 | cmd2
上記のようなパイプで繋いだコマンドで、cmd1の終了ステータスを拾いたいのですが、
どうしたらよいのでしょうか?
0818名無しさん@お腹いっぱい。2005/08/04(木) 14:25:13
csh -c 'cmd1 | cmd2'
0819名無しさん@お腹いっぱい。2005/08/04(木) 14:45:12
出来ました、ありがとうございます。
0820名無しさん@お腹いっぱい。2005/08/04(木) 14:55:23
(((cmd1; (echo $? >&3)) | cmd2 >&4) 3>&1 | (read x; exit $x)) 4>&1
echo $?

うーん、美しくない。
0821名無しさん@お腹いっぱい。2005/08/04(木) 22:10:15
一瞬lispに見えたw
0822名無しさん@お腹いっぱい。2005/08/04(木) 23:58:53
>>814
tr -d '\n'
0823名無しさん@お腹いっぱい。2005/08/05(金) 00:59:04
>>817
bash の(たぶん)3.0じゃないと使えないと思うけど、
$ echo $PIPESTATUS[0]
とか、出来る。
ちなみに配列だから、
$ echo ${PIPESTATUS[*]}
で、全部見れる。

あと、ちょっと違うけど、
$ set -o pipefail
とかもある。

08248232005/08/05(金) 01:01:30
PIPESTATUS、bash-2.05bにもあったよ。
pipefailが、3.0からだった。
0825名無しさん@お腹いっぱい。2005/08/05(金) 02:17:49
今/home/.emacsがあるとして、ユーザディレクトリにそれぞれコピーするには
どう書けばいいですか?所有者ももそれぞれのユーザに設定できますか?
0826名無しさん@お腹いっぱい。2005/08/05(金) 02:32:28
>>825
/etc/skel に置いとけ
0827名無しさん@お腹いっぱい。2005/08/05(金) 02:35:58
シェルスクリプトのスレよりもくだ質が似合いの質問者だな。
0828名無しさん@お腹いっぱい。2005/08/05(金) 02:54:40
>>826 >>827
そんなぁ・・・
そこをなんとか・・・
0829名無しさん@お腹いっぱい。2005/08/05(金) 03:15:53
くだ質いけって言われたのになんでここで粘るんだ?
だだこねる相手はママだけにしとけよ。

次の方、どうぞ↓

0830名無しさん@お腹いっぱい。2005/08/05(金) 07:43:52
なんで怒ってるの?
0831名無しさん@お腹いっぱい。2005/08/05(金) 07:47:09
$HOMEに押し着せの.emacsを強制コピーしてくる
シス管が居て、迷惑してるのですが、
これを拒否するにはどうしたらいいでしょうか?

ちなみに、root権限で上書きコピーしてくるため、
一般ユーザーのパーミッション設定では防げません。
あと、.emacsだけじゃなく、$HOME/.profile
$HOME/.xinitrcとかもコピーで潰されるので大迷惑です。
0832名無しさん@お腹いっぱい。2005/08/05(金) 08:17:23
.emacs というディレクトリ作っといたら?
0833名無しさん@お腹いっぱい。2005/08/05(金) 08:34:38
>>831
#!/bin/sh
cat <<EOF | mail root
From: $USER

あなたのホスト管理はクソです。
いますぐ.emacsをroot権限で上書きするというアホな行為をやめてください。
EOF
0834名無しさん@お腹いっぱい。2005/08/05(金) 08:53:27
>>831
自分の.emacs を、.my-emacs とかにかえて、
シェルのalias を使って、
alias emacs="emacs -q -l .my-emacs"
とかしとく。

.profile の方も、同じような考え方で、
bash --norc --noprofile の後、自分のprofileを読み込むようなscriptを書いといて、
毎回、loginし直す。(面倒だけど)

zsh 、ksh、tcsh等、対話的に使うshellを他のにするとかでもいいんじゃん?

.xinitrcは、
export XINITRC=$HOME/.my-xinitrc
を設定しといて、startx。
で、どうよ。

>>833 みたく、管理者に一言いうのが早いかもしんないけど。
0835名無しさん@お腹いっぱい。2005/08/05(金) 11:18:52
ln -s /etc/passwd ~/.emacs
0836名無しさん@お腹いっぱい。2005/08/05(金) 11:36:49
どういうタイミングでどういう手段で何が上書きされるのか。
ログインシェルは何か。自分の権限でcronやchshは使えるか。
などによっていろいろと対抗手段は考えられるけど、情報不足。
0837名無しさん@お腹いっぱい。2005/08/05(金) 11:41:59
>>825 に対する皮肉として書いた釣りなのに、
こんなに釣りにつき合ってくれてありがとう。
0838名無しさん@お腹いっぱい。2005/08/05(金) 11:48:34
釣られすぎだな。
0839名無しさん@お腹いっぱい。2005/08/05(金) 13:03:52
      ∧_∧ハゥッ
   ∧_(Д`; )
  ( ・∀・)玉  つ
  (っ  ≡つて ヽ チーン!
  して_)_ノw (_)
玉を砕くと書いて「玉砕」と言う。
0840名無しさん@お腹いっぱい。2005/08/05(金) 13:12:34
835に1票
0841名無しさん@お腹いっぱい。2005/08/05(金) 13:32:33
>>835 も面白いけど、
ふつー、rm -f してから cpするだろうから効果なし。
0842名無しさん@お腹いっぱい。2005/08/05(金) 16:40:35
そのふつーが期待できる管理者ならユーザの.emacsを上書きしたりなぞしない。
0843名無しさん@お腹いっぱい。2005/08/05(金) 17:32:09
http://makimo.to/2ch/pc5_unix/996/996949546.html
の3の書き込みなんですが、意味は分かるんですが
なぜ {, という書き方なんでしょうか。
そのままぐぐってみてもヒットしないので
展開の書式を解説しているサイトを教えてください。
0844名無しさん@お腹いっぱい。2005/08/05(金) 17:35:55
(zsh)Brace Expansion
13.6 Brace Expansion
====================

A string of the form `FOO{XX,YY,ZZ}BAR' is expanded to the individual
words `FOOXXBAR', `FOOYYBAR' and `FOOZZBAR'. Left-to-right order is
preserved. This construct may be nested. Commas may be quoted in
order to include them literally in a word.
■ このスレッドは過去ログ倉庫に格納されています