[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 801- 901- 2chのread.cgiへ]
Update time : 05/09 21:40 / Filesize : 275 KB / Number-of Response : 969
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

シェルスクリプト総合@LINUX Part3



1 名前:login:Penguin [2007/07/10(火) 23:17:13 ID:qGthZdME]
UNIX板のスレを見ている方も多数おられるかと思いますが、
まあそれはそれとして、BASHウゼーとか言われる心配なく
平和にLINUX的スクリプト談義しましょうよ。

初めての自作スクリプト、自信ないから見てください。な初心者から
トリッキーな技を駆使した作品を披露したい、蘊蓄を語りたい上級者まで
いろいろな人に参加して頂けると嬉しいです。

perlやらPythonやらの話が混ざっても良いんでない?

【sed】シェルスクリプト総合@LINUX Part2【awk】
pc11.2ch.net/test/read.cgi/linux/1154578200/
pc8.2ch.net/test/read.cgi/linux/1121994321/

>>2-5あたりに色々と。


91 名前:73ですが mailto:sage [2007/09/01(土) 22:39:45 ID:uwRTp3HZ]
>>76
仕様はおっしゃるとおりです。
その際のスクリプトも教えてくだされば幸いです。
なお、他のスクリプトは現在のところ動作していません。わたしの知識不足なのだろうと思うのでもうすこし調べてみます。
#0は補ってはあるのですが...
ついでといってはなんですが、awkの本でおすすめの本などありましたら教えていただけませんか?

92 名前:login:Penguin mailto:sage [2007/09/02(日) 04:19:30 ID:WMH1r7G1]
>>91
オライリーの sed & awk
てかawkの本なんて何冊もないって。


93 名前:login:Penguin mailto:sage [2007/09/02(日) 08:46:56 ID:ToB27R8d]
本命 足立さんの訳してる awk 本
大穴 awk 256 本

94 名前:login:Penguin mailto:sage [2007/09/02(日) 20:47:44 ID:VmAuZafy]
awk256倍はDOS時代からある骨董本で内容もふざけまくっているが、初心者が
「正規表現」「連想配列」という二つのキモを学習するにふさわしい内容。
読み終わったあとも、巻末の関数一覧がずっと使える。未だに刷を重ねてるけど
愛用者もおおいんじゃない?
大して御本家3人の書いたawk本は内容が高度な上に散発的で、調べたいことが
すぐに出てこなくて使いにくい

>>91
>>76のがその仕様のスクリプトなんだけど。うまく動かないのは、スペースとかが
ちゃんとコピペされてないからなんじゃないの?

95 名前:73ですが mailto:sage [2007/09/02(日) 21:37:03 ID:71yMDj2y]
>>92-94
本の紹介ありがとうございました。
>>94
気づきませんでした。すいません。スペースの問題などを再確認してみます。
またなにかあったら伺うかもしれません。よろしくおねがいします。

96 名前:login:Penguin mailto:sage [2007/09/02(日) 21:40:05 ID:QLbcFUyG]
DOS時代ってのはいつまでを言うんだ?

97 名前:login:Penguin mailto:sage [2007/09/02(日) 21:55:05 ID:ToB27R8d]
awk 256 本の話の文脈としては、MS-DOS上のawk実装の時代かな

98 名前:login:Penguin mailto:sage [2007/09/02(日) 22:03:47 ID:VmAuZafy]
>>97
そう。今の版じゃ改訂されてるのかもしれないが、俺の持ってるのだと
gawkをDOSに移植したjgawkとかいうのを下敷きにしていて、中には486を乗せたキューハチだと
スクリプトの速度が向上したとか、パイプの実行速度が遅いのはUNIXみたいな本物のパイプじゃないからとか、
そんな話題が満載

99 名前:login:Penguin mailto:sage [2007/09/02(日) 22:04:37 ID:QLbcFUyG]
MS-DOS上のawk実装の時代ってのはいつを言うんだ?



100 名前:>>84 [2007/09/04(火) 00:34:58 ID:3rxVdbk9]
おくらばせながら、ありがとうございますm(_ _)m

101 名前:login:Penguin mailto:sage [2007/09/06(木) 08:15:09 ID:33eRwNa2]
指定されたディレクトリ以下にあるディレクトリ一覧を返してくれるコマンドはありませんか?

/data/ をTOPディレクトリとしますと
/data/hoge/
/data/piyo/
/data/moge/

等が帰ってくるコマンドです。で、この際 /data/hoge/direc/ みたいに、TOPディレクトリの
孫ディレクトリ以下は返さないで欲しいんです。TOPディレクトリの子ディレクトリのみを
返して欲しいのです。そして for TARG in command; do 処理; done のように
for文で1つ1つのディレクトリを処理したいのです。

それからもう1つ、指定されたディレクトリ以下の子ディレクトリの数を返すには
ls -l /data/ | grep ^d | wc -l
でいいのでしょうか?ディレクトリだと ls -l した時に必ず最初が dから始まるので
これでディレクトリのみがマッチして、後はwcでその行数を数えればいいかと思っているのですが
今の所これでちゃんと動作していますが、不具合が発生するようなケースは想定されますか?
ディレクトリの数も孫ディレクトリ以下は数えません(再帰処理しない)。

昨日 basename と言う便利なコマンドを知った程度のレベルの人間ですので
awk や sed 等の難しいコマンドはなるべく使わずに実現したいのですが、出来ませんかねぇ?
宜しくお願い致します。

102 名前:login:Penguin mailto:sage [2007/09/06(木) 08:27:57 ID:QTrKtnCG]
>>101
ls -d /data/*/

103 名前:login:Penguin mailto:sage [2007/09/06(木) 08:30:08 ID:QTrKtnCG]
/data/.x/ とかも考慮したいなら find で。

104 名前:login:Penguin mailto:sage [2007/09/06(木) 08:31:55 ID:33eRwNa2]
>>102
あっちゃー・・・・そんな簡単なコマンドでこんな素晴らしい出力が得られるんですか!
LinuxのCUIって本当に高機能ですね・・・素晴らしいです。本当にありがとうございます。

ls -l /data/ | grep ^d | wc -l
ってやるより
ls -ld /data/*/ | grep ^d | wc -l
ってやる方が良いのでしょうか?どんなファイルやディレクトリがあっても確実に動作するような
書き方をしたいのですが・・・。

105 名前:login:Penguin mailto:sage [2007/09/06(木) 08:32:01 ID:QFjDOBHf]
属性が見えて良ければ
ls -d /data/*|grep "^d"



106 名前:login:Penguin mailto:sage [2007/09/06(木) 08:33:56 ID:QFjDOBHf]
-l忘れてた



107 名前:login:Penguin mailto:sage [2007/09/06(木) 10:26:24 ID:QTrKtnCG]
>>104
> ls -ld /data/*/ | grep ^d | wc -l
なんで grep するんだ?

108 名前:login:Penguin mailto:sage [2007/09/06(木) 11:58:40 ID:rZQRUej8]
ls -1d /data/*/ /data/.*/

/data/../ もヒットするのが難点だけどな。ってかあれだ。つ「man ls」

109 名前:login:Penguin mailto:sage [2007/09/06(木) 16:47:27 ID:40ywKZW4]
>>101
求めてることが出来たのであればどんなコマンドでもいいけど
find の使い方も知っておいたほうがいいと思う。

> 不具合が発生するようなケースは想定されますか?
> ディレクトリだと ls -l した時に必ず最初が dから始まる
ディレクトリへのシンボリックリンクがあった場合の扱いをどうするか。

さらに言えばリンクの対象がどこにあるか
ln -s /data/A /data/B と ln -s /tmp/C /data/B の違いとか。



110 名前:login:Penguin mailto:sage [2007/09/06(木) 16:55:32 ID:QTrKtnCG]
ls -Ap /data | grep /$
でよかったか。

>>109
> find の使い方も知っておいたほうがいいと思う。
同意。

111 名前:login:Penguin mailto:sage [2007/09/06(木) 17:08:55 ID:ZccH/OF/]
なのに誰もfindを使った答を書かないのはなんでだw
101への課題?

112 名前:login:Penguin mailto:sage [2007/09/06(木) 20:00:39 ID:QTrKtnCG]
>>111
それもあるし、単にめんどうだし。

113 名前:login:Penguin mailto:sage [2007/09/07(金) 11:30:33 ID:BZSReuYl]
んじゃ、俺の回答に採点してくれ
find /data -type d -maxdepth 1

114 名前:109 mailto:sage [2007/09/07(金) 17:14:59 ID:NgwMB5/h]
>>113
二ヶ所で減点。

1) find の出力に TOPディレクトリ(/data 自身)も含まれてる。
>>101 を読むとTOPディレクトリそのものは不要だと思う。

2) GNU find version 4.2.27 だと -maxdepth の位置で warning が出た。
find: warning: you have specified the -maxdepth option after a non-option argument -type, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it). Please specify options before other arguments.

115 名前:login:Penguin mailto:sage [2007/09/07(金) 17:35:19 ID:BZSReuYl]
>>114
なるほど。非常に参考になった。
模範解答を頼む。

116 名前:login:Penguin mailto:sage [2007/09/07(金) 17:39:52 ID:aiZtBudz]
>>115
もう一回自分で書いてみたら?

117 名前:login:Penguin mailto:sage [2007/09/07(金) 19:24:55 ID:Txvf/Wl4]
find /data -mindepth 1 -maxdepth 1 -type d -exec ...

shopt -s nullglob
for i in /data/{,.{[!.],.?}}*/
do ...

こんなんでいかが

118 名前:login:Penguin mailto:sage [2007/09/07(金) 19:45:52 ID:ezpNZgi5]
cat hoge | awk
に似ている。

119 名前:login:Penguin mailto:sage [2007/09/07(金) 20:30:25 ID:BZSReuYl]
>>116
OK。これでどうだ?
find /home/* -maxdepth 0 -type d




120 名前:login:Penguin mailto:sage [2007/09/08(土) 04:46:18 ID:WlyFgm6n]
>>117 でもう答え出てるじゃん。

>>119
/home/.xxx/ とかが出ない。
* 使うなら find 使う意味ない。

121 名前:login:Penguin mailto:sage [2007/09/08(土) 14:42:47 ID:vllGfkN4]
>120
>* 使うなら find 使う意味ない。
上下別々の回答なんじゃないの?

122 名前:login:Penguin mailto:sage [2007/09/11(火) 03:08:21 ID:997sWGjJ]
bashrc の書き方もこのスレでいいですか?

123 名前:login:Penguin mailto:sage [2007/09/12(水) 11:40:47 ID:EatE1MlG]
#!/bin/sh -f
ls *.dat > list.txt

なぜか走らん。

124 名前:login:Penguin mailto:sage [2007/09/12(水) 17:16:53 ID:A49nKXNq]
>>123
子プロセスとして(?)起動するシェルに -f が渡らないんだと思う。
/bin/sh -f hoge.sh とか
あらかじめ /bin/sh -f で起動したシェルで
./hoge.sh みたいにすると
-f が有効になる。

125 名前:login:Penguin mailto:sage [2007/09/12(水) 17:21:21 ID:EatE1MlG]
>>124
エラーで *.dat: ファイルもディレクトリもありません とでる
ワイルドカードが原因かと思ったけど、hoge*でも同様のエラー

シェルにしたら走らず、コマンドラインで直接投げたら走る
なんでだろ

126 名前:124 mailto:sage [2007/09/12(水) 17:27:12 ID:A49nKXNq]
>>125
/bin/sh -f の -f がどんな意味かわかってる?

あと、シェルとシェルスクリプトはちゃんと区別したほうがいい。

127 名前:login:Penguin mailto:sage [2007/09/12(水) 17:33:44 ID:EatE1MlG]
!/bin/cshで走ったわ
コンソールがcshだった

128 名前:login:Penguin [2007/09/12(水) 20:01:20 ID:9HkBr7tD]
複数のpasswdファイル(passwd_A、passwd_B)を結合して、同じユーザ名があった場合
passwd_Aのものだけを残すというようなことをしたいのですがどうすればよいでしょうか?

129 名前:login:Penguin [2007/09/12(水) 20:12:55 ID:nfcPR4Gc]
いったんファイルを結合する
一行ずつ上から順に読んでパスワードファイルに書き込む
書き込んだらそのユーザー名を別ファイルに書き出す
その別ファイルにユーザー名がないことを確認してから
パスワードファイルに書き込めばよい



130 名前:login:Penguin mailto:sage [2007/09/12(水) 22:19:22 ID:qqfxe9V8]
while read t ;do
if [ "`grep ^${t%%:*}: passwd_A`" ];then
continue
else
echo $t >>passwd_A
fi
done <passwd_B


131 名前:login:Penguin mailto:sage [2007/09/12(水) 22:53:21 ID:SML918nz]
んだば awk で。
awk -F: '{
    t[$1] = $0;
}
END {
    for (e in t)
        print t[e];
}' passwd_B passwd_A

132 名前:login:Penguin mailto:sage [2007/09/12(水) 23:49:46 ID:lhLTsTba]
awk -F: '!($1 in t){print;t[$1]=1;}' passwd_A passwd_B

133 名前:login:Penguin [2007/09/13(木) 21:53:28 ID:8j1+julM]
aaa.txtの中身
20070109,170000,170000,167000,170000,4
20070110,168000,168000,168000,168000,10
20070115,171000,171000,163000,169000,500


2007/01/09,170000,170000,167000,170000
2007/01/10,168000,168000,168000,168000
2007/01/15,171000,171000,163000,169000
のように
YYYY/MM/DDと表示を変更する
最後の,からあとを削除してbbb.txtとして出力したいと思っています
どのようにすればいいものでしょうか

4文字目と5文字目の間に/を挿入するということがsedでできなくて悩んでおります
よろしくお願いいたします


134 名前:login:Penguin mailto:sage [2007/09/13(木) 22:06:02 ID:OVx1tSlg]
cat /tmp/aaa.txt | gawk -F, '{printf("%04d/%02d/%02d,%s,%s,%s,%s\n", substr($0,1,4),substr($0,5,2),substr($0,7,2),$2,$3,$4,$5)}' > bbb.txt

135 名前:login:Penguin mailto:sage [2007/09/13(木) 22:08:03 ID:G9V8Phhb]
\(\)でグルーピング、\{\}でマッチする回数の指定。
グルーピングしたパターンは後で\1,\2で参照出来る。
\を忘れるなよ。

136 名前:login:Penguin mailto:sage [2007/09/13(木) 22:09:20 ID:G9V8Phhb]
あ、ごめん、>135はGNU sedの話

137 名前:login:Penguin mailto:sage [2007/09/13(木) 22:25:32 ID:8j1+julM]
>>134
ありがとうございます
gwakというのも勉強してみようと思います





138 名前:login:Penguin mailto:sage [2007/09/13(木) 22:52:13 ID:8j1+julM]
>>134
manを見てみたら いろんなところで使用できそうです
本当にありがとう

139 名前:login:Penguin mailto:sage [2007/09/13(木) 23:24:02 ID:saILvvtf]
>>134
catは要らんだろ。



140 名前:login:Penguin mailto:sage [2007/09/14(金) 00:50:00 ID:uh85VpLs]
正規表現も勉強した方がよろしいかと>>138

141 名前:login:Penguin mailto:sage [2007/09/14(金) 12:28:52 ID:hH9EcwDJ]
ある XXX っていう名前を含んだプロセスを全て殺したい時、
ps aux | grep XXX | grep -v grep | awk '{print $2}' | kill
ではだめなのに
ps aux | grep XXX | grep -v grep | awk '{print $2}' | xargs kill
ではOKなのはなぜですか?

142 名前:login:Penguin mailto:sage [2007/09/14(金) 12:34:24 ID:18sjQ9F0]
>>141
kill って標準入力を受け付けないんじゃない。
ところで pkill XXX じゃだめなの?

143 名前:login:Penguin mailto:sage [2007/09/14(金) 12:37:30 ID:hH9EcwDJ]
>>142
そうなのかなと思って
for p in $(ps aux | grep XXX | grep -v grep | awk '{print $2}'); do
    kill "$p"
done
ってのもやってみたんですが、だめだったんですよ。

144 名前:login:Penguin mailto:sage [2007/09/14(金) 17:32:35 ID:Ney/3ygS]
スクリプトでタイマー作れませんか?
一定間隔ごとに単純にコマンド出すだけじゃなくて
処理ごとに条件分岐してタイマーを止めたりコマンドが成功
するまで繰り返したりしたいのですが

145 名前:login:Penguin mailto:sage [2007/09/14(金) 20:21:33 ID:KxObz0sB]
>>144
sleep使って、て程度で良いなら作れるような気しかしないんだけど、具体的にどうしたいのか書いたのが良いと思うぞ。

146 名前:login:Penguin mailto:sage [2007/09/14(金) 20:32:43 ID:RM0kquC+]
>>144
どこまで出来たの?

147 名前:login:Penguin mailto:sage [2007/09/14(金) 23:57:41 ID:XHXILi6a]
>>143
だめってどうダメだったのかわからんと。

for p in $(ps aux | grep smbd | grep -v grep | awk '{print $2}'); do
"kill "$p"
done

これでやったらちゃんと動いたよ。スクリプトの問題じゃなくて
単に権限がなくてkillできなかっただけでは?

148 名前:login:Penguin mailto:sage [2007/09/15(土) 16:55:13 ID:/cIKvz/T]
>>147
さっきやってみたら出来た。。。

間違って mplayer を40個くらい起動してしまって、そこでそのスクリプトを
叩いたつもりだったんだけど、焦ってなんか間違ってたのかもしれない。

とりあえず今度からは xargs のほうを使うようにするよ。

149 名前:login:Penguin mailto:sage [2007/09/15(土) 17:28:32 ID:YiwEKkpX]
いやだからpkill使えって



150 名前:login:Penguin mailto:sage [2007/09/15(土) 17:49:23 ID:X+i1f7J3]
command | command みたいな

cat hoge.txt | grep piyo

書き方があるじゃないですか? cat hoge.txt で出力される標準出力をパイプかませて
その出力内容に対して grep piyo をかける と言うような。
これと
xargs ってコマンドがあるじゃないですか?その違いがよく分からないのですが・・。
cat hoge.txt | xargs grep piyo

みたいな?

151 名前:login:Penguin mailto:sage [2007/09/15(土) 18:13:14 ID:YiwEKkpX]
「cat hoge.txt | xargs grep piyo」=「grep piyo `cat hoge.txt`」



152 名前:login:Penguin mailto:sage [2007/09/15(土) 18:42:58 ID:X+i1f7J3]
>>151
ほぉほぉ・・・・

cat hoge.txt | xargs grep piyo が
grep piyo `cat hoge.txt`
と同じならば
cat hoge.txt | grep piyo

grep piyo hoge.txt

ん?なんか混乱してきた・・・イマイチはっきりと分からない・・・

153 名前:login:Penguin mailto:sage [2007/09/15(土) 19:03:27 ID:8eNJORpc]
argっていうぐらいだから引数に展開してくれるのだろ
その場合hoge.txtの中身はファイル名でないとだめ

154 名前:login:Penguin mailto:sage [2007/09/15(土) 19:15:07 ID:jJyNjt7I]
もう分かってるかもしれないけど、xargsは標準入力をコマンドライン引数に変換するだけ。
echo 'file1 file2 hoge' | xargs rm
 ↓
rm file1 file2 hoge

155 名前:login:Penguin mailto:sage [2007/09/15(土) 19:47:59 ID:X+i1f7J3]
むぅ・・・

echo `file1 file2 hoge` | xargs rm

rm file1 file2 hoge
となるならば
echo `file1 file2 hoge` | rm

どう展開されるんですか? すみません、ほんと頭弱くて。

156 名前:login:Penguin mailto:sage [2007/09/15(土) 19:51:39 ID:YiwEKkpX]
引数と標準入出力の区別がまだついてなくて、全部「入力」として
ごちゃまぜの段階でしょ?まずそれを考えてみるんだ>155

157 名前:login:Penguin mailto:sage [2007/09/15(土) 23:18:03 ID:+DsxitZ3]
>>154の echo 'file1 file2 hoge' | xargs rm
>>155の echo `file1 file2 hoge` | xargs rm

どこが違うか理解してからにしろ


158 名前:login:Penguin mailto:sage [2007/09/15(土) 23:25:38 ID:PpA5ThvC]
こんな初歩の初歩みたいなことに、どうしてそんなに高飛車になれるんだ。

159 名前:login:Penguin mailto:sage [2007/09/16(日) 01:01:56 ID:S5o7UTSR]
初歩の初歩は自力で身に付けてから来てくれよ。



160 名前:login:Penguin mailto:sage [2007/09/16(日) 01:06:18 ID:BSYCrrV+]
タコタコ

161 名前:login:Penguin mailto:sage [2007/09/17(月) 04:16:34 ID:nqz563FT]
convmv -r -f sjis -t utf-8 * --notest
で、再帰的にカレントディレクトリ以下のファイル、ディレクトリ全てに対して
sjisからutf-8に変換をかけるコマンドを打ったのですが、sjisとeuc-jpが混在していて
convmvの仕様だと 1ファイルでも -f で指定した文字コード以外の文字コードのファイルが
存在した場合はそこで全ての変換処理が実行されなくなってしまいます。
違う文字コードの場合は除外して残りを全て処理してくれるオプションは無いかとman convmv
を読んで見ましたが、無いようです。
仕方が無いので、これをシェルスクリプトで実現したいと思います。
実際にやりたいコマンドは
convmv -r -f sjis -t utf-8 /data/* --notest で、これで変換できないファイルは
convmv -r -f euc-jp -t utf-8 /data/* --notest で、全てのeuc-jpとsjisをutf-8にする事です。

for TARG in `find /data | nkf -w8`
do
    convmv -f sjis -t utf-8 ${TARG} --notest
    convmv -f euc-jp -t utf-8 ${TARG} --notest
done

これで、sjisのファイルだろうがeuc-jpのファイルだろうが必ずutf-8になると思われますが
いけると思いますか? | nkf -w8 をかませているのは、こうしないとターミナルで見た限りだと
文字化けしたファイル名でそのまま表示されるので、これだと多分ファイルにアクセスできないだろう
との配慮から、ちゃんとしたファイル名で見えるようにしたつもりです。

162 名前:login:Penguin mailto:sage [2007/09/17(月) 08:49:52 ID:hnYIly1T]
>>161
qkc最強伝説

163 名前:login:Penguin mailto:sage [2007/09/17(月) 11:57:35 ID:nqz563FT]
>>162
hp.vector.co.jp/authors/VA000501/
これですよね?

しかしこれはconvmvとは全く別物のようです。

convmv => ファイル"名"の文字コードを変換する ←私はコレが必要
qkc   => テキストファイルの"中身"の文字コードを変換する ←これは違う・・・

なので使えないみたいです。

ちなみに >>161で書いたスクリプトを実際に動かしてみた所、LinuxサーバのCPU使用率が
100%になって固まっちゃいました。無限ループをしているかファイル名取得に失敗しているか
よく分かりませんがダメでしたOTL

164 名前:login:Penguin mailto:sage [2007/09/17(月) 12:18:44 ID:CDwJTqgj]
よくわからんのだが、nkf -gで文字コードの判別してやりゃ良いんじゃねぇの?

165 名前:login:Penguin mailto:sage [2007/09/17(月) 12:56:16 ID:RA5G8Fdp]
while ! convmv -f sjis -t utf-8 -r /data --notest ; do
convmv -f euc-jp -t utf-8 -r /data --notest
done
なんか、どうよ?
文字コード判定がいまいちなのか誤認してくれたりするので --notest とって、ざっと眺めてからやる事を推奨。


166 名前:login:Penguin mailto:sage [2007/09/17(月) 13:00:08 ID:85s13mgP]
--notest 外して試してみればーじゃん。

167 名前:login:Penguin mailto:sage [2007/09/17(月) 13:21:00 ID:hplwR1nR]
echo $RANDOM

で結果に乱数を返したいんですけど、
0〜9までの一桁の結果のみ返したい場合の指定方法とかってありますか?

168 名前:login:Penguin mailto:sage [2007/09/17(月) 13:53:15 ID:MlIRuyKv]
$RANDOM % 10

169 名前:login:Penguin mailto:sage [2007/09/17(月) 15:09:07 ID:nqz563FT]
>>164
nkf はファイル"名"ではなくて、ファイルの"中身"についての文字コードを
調べるんですよね?テキストファイルに対して実行するとShift-JISと言う出力が得られ、
.exeファイル等に実行すると Binary と表示されました。
なので、これは全く別物です。

>>165
おお・・・
それはつまり
convmv -f sjis -t utf-8 -r /data --notest
で、元ファイルがsjisじゃなかったときは元ファイルがeuc-jpとして処理を繰り返すんですね。
しかしその場合、仮に1つでも元ファイルがsjisだった場合は?と言うか・・・

それ実行してみたのですが、無限ループに陥りました。何度も同じファイルを判定して
これsjisじゃないよ〜って帰ってきます。

よくよく考えると -r /data で既に再帰的に繰り返す処理なのに、それをさらにwhileでループさせて
いるんですよね。二重ループ状態ですか。
while ! convmv -f sjis -t utf-8 -r /data --notest ; do
これで、とりあえず convmv -f sjis -t utf-8 -r /data --notest が実行される
→実行された時に1つでも違うファイルが存在していてエラー
→convmv -f euc-jp -t utf-8 -r /data --notest が実行される
→実行された時に1つでも違うファイルが存在していてエラー
またconvmv -f sjis -t utf-8 -r /data --notest が、最初にエラーで止まったファイルも含んで
最初から実行される>当然また同じファイルでエラーを起こす>convmv -f euc-jp -t utf-8 -r /data --notest が
また実行されてまたこれも最初から処理してしまう>これを永遠に繰り返して無限ループに陥る。
ダメみたいですOTL

>>166
--notestはずして試してみてますが、エラーで弾かれます。



170 名前:login:Penguin mailto:sage [2007/09/17(月) 15:30:26 ID:kUn2DAgf]
>>169
いや、ファイル名のコードをnkfで調べりゃいいじゃん、てことだったんだけど。

171 名前:login:Penguin mailto:sage [2007/09/17(月) 15:35:55 ID:kUn2DAgf]
念のため。
for T in `ls ~`
do
C=`echo "$T" | nkf -g`
echo $T,$C
done
ファイル名の文字コードを調べてると思うんだが。

172 名前:login:Penguin mailto:sage [2007/09/17(月) 16:38:42 ID:nqz563FT]
>>170-171
違うと思うなぁ・・・。

>>171のスクリプト実行してみたけど
これは ls ~ で表示されるファイル名リスト全体、、、そうだなぁ、、例えば
a.txt
b.mp3
c.tar
d.gz
e.tar.gz

とか日本語も含むファイル名全てが列挙されると思うけど、それらのファイル名リスト
全体を1つのテキストファイルとみなして、テキストファイルの中身(つまりファイル名が列挙されてる)
に対して文字コード変換をかけた結果を echo で出力しているんじゃないですか?
だからnkf は ファイル"名"の文字コードを調べるんじゃなくて、あくまでもテキストファイルの中身
の文字コードを調べるんだと思いますが。それこそqkcみたいな動作?
convmvは全くそれとは性格が異なる物だと思いますが、、非常にこの辺ややこしい・・・。

173 名前:login:Penguin mailto:sage [2007/09/17(月) 16:45:55 ID:8vN1DPCo]
なんでこんなに全然わかってないのに自信満々なのだろうか

174 名前:login:Penguin mailto:sage [2007/09/17(月) 16:47:06 ID:rlyHM/pf]
>>161
>>164 の意見を採用して書いてみた。
for を while に変えたのは俺の趣味。

find /data | while read TARG ; do
 File=$( nkf -g <<< "$TARG" )
 case "$File" in
   Shift_JIS*) Code=sjis ;;
   EUC-JP*) Code=euc-jp ;;
UTF-8*) continue ;;
 esac
 echo "$File: Convert to $Code" ## お好みで
 convmv -f "$Code" -t utf-8 "$TARG" --notest
done

ファイル名程度の短い文字列だと nkf の文字コード判定の
精度はあまりよくないが、やらないよりはマシだろう。


175 名前:login:Penguin mailto:sage [2007/09/17(月) 16:52:30 ID:HxbR0j5A]
文字コードが違うファイル名が混在しているディレクトリって。
どうしてそうなったかが気になる

176 名前:login:Penguin mailto:sage [2007/09/17(月) 16:55:54 ID:4XOwAbVo]
ローカルで作ってSambaで作ってWebDAVあたりで作ってとやってしまうと
起きるな?>混在。

後はデータ中の文字列を元にファイルを作ったりすると、うっかり
混在状態になったり。

177 名前:login:Penguin mailto:sage [2007/09/17(月) 17:22:02 ID:kUn2DAgf]
>>172
>>173と同意なんだが、想像の斜め上な方向に理解してるのね。と理解。
なして>>171を実行してみた上で>>172になるのかわからん。。。
つまり、>>172としては、「a.txt あ.txt い.txt」の3つのファイルがあると、
 a.txt, ASCII
 あ.txt,UTF-8(とか)
 い.txt,EUC-JP(とか)
てならず、
 a.txt,BINARY
 あ.txt,BINARY
 い.txt,BINARY
となった、てこと?

>>174
半角カナ使ってなけりゃ、それなりの精度なんじゃねぇかと思うんだけど、どうだろ。

178 名前:login:Penguin mailto:sage [2007/09/17(月) 17:29:26 ID:kUn2DAgf]
>半角カナ使ってなけりゃ、〜
↑勘違い。すま。

179 名前:login:Penguin mailto:sage [2007/09/17(月) 19:31:50 ID:nqz563FT]
>>173
すみませんOTL。

>>174
そのスクリプト動かしてみたのたですが、 echo ${File}を加えて確認した所
ほとんどのファイルが ASCII と出力されていて、少しだけ Shift-JISという出力が得られました。
って事は?Shift-JISとASCIIが混在しているという事でしょうか?
と言うかそもそもASCIIっていったいどういう・・?
euc-jp sjis utf-8 の3種類しか基本的には知らなくていいと思っていたのですが、4つ目の文字コード
も混在している(というよりeuc-jpのファイルは存在しなくてsjisとASCIIの2つが混在?)と言う事でしょうか。
と言うか convmv --list してみたら asciiってあるし・・・・。

>>176
そうそう、さらにFTPも混ざったりssh + rsyncとかでファイル持ってきたりすると
もう今ぐちゃぐちゃになってて、UTF-8に統一したいんですよ。。。
>>177
.txtの拡張子のファイルは BINARYはでません。

ん?って事は nkf -g ではファイル"名"の文字コードを判別しているって事ですか?
で、その出力がASCIIとShift-JIS、その他としてはBINARYの3種類の状態(だと思う)の場合は
convmv -f ascii -t utf-8
convmv -f sjis -t utf-8
でそれぞれ変換かければいいのかな・・・。なんか難しすぎて頭痛くなってきたOTL。
でもなんか全面的に私が間違っていた感じがするので、その点については皆様方には
大変ご迷惑をお掛けしておりまして申し訳ありません。



180 名前:login:Penguin mailto:sage [2007/09/17(月) 20:51:38 ID:kUn2DAgf]
>>179
なんていうか、なぁ。

ASCIIってのは日本語使ってなけりゃASCIIだわな。ちと語弊あるけど。「a.txt」とか。
で、オレの>>177で示したのは、>>174をオレ解釈したところ、
「a.txt」と「(UTF-8な)あ.txt」と「(EUC-JPな)い.txt」が混在してると、いっしょくたになったのが
コード判別にかかって、結局コード判別できなくって「BINARY」って判別されるってことか? と。
オレの説明わかり難かったとは思うけどな。

でもってnkf -gだが、たんに「入力された」のの文字コード体系を調べるだけであって、それが
「ファイルの中身」なのか「ファイル名」なのかは、どっちを指定、てか、nkfに入力したか、て
違いだけ。わかる?

ついでに日本語のファイル名がShift-JISだけなら、SJIS→UTF8に変換指定するだけでokやな。

そんなわけで、まちっと勉強しれ。

181 名前:login:Penguin mailto:sage [2007/09/17(月) 21:22:34 ID:rlyHM/pf]
>>179
ああ、そういや ASCII を忘れてた。w
解説は >>180 を見てもらうとして、
それを踏まえて >>174 を改良すると、こんな感じかな。
後は自分で調べてみな。

find /data | while read TARG ; do
 File=$( nkf -g <<< "$TARG" )
 case "$File" in
   Shift_JIS*) Code='sjis' ;;
   EUC-JP*) Code='euc-jp' ;;
   ISO-2022-JP*) Code='iso-2022-jp' ;;
   ASCII*|UTF-8*) echo "$TARG: $File"; continue ;;
   *) echo "$TARG: $File: Not supported format."; continue ;;  
 esac
 echo "$File: Convert from $Code to UTF-8." ## お好みで
 convmv -f "$Code" -t utf-8 "$TARG" --notest
done

>>180
> 「a.txt」と「(UTF-8な)あ.txt」と「(EUC-JPな)い.txt」が混在してると
判定はファイルごとに行うからこれで「BINARY」にはならないはず。

「(UTF-8)あ(EUC-JP)い.txt」とか、複数の文字コードで構成された
ファイル名だと誤判定と言うか、期待通りにはならないと思う。

こういうのもきちんと判定したいのなら ack がお勧め。
こんなファイル名に出くわす事はまずないだろうけどな。w

182 名前:login:Penguin mailto:sage [2007/09/17(月) 22:20:42 ID:nqz563FT]
>>180
なるほど、英数字だけの場合はASCIIなんですね・・。
では、 a.txt(ASCIIですよね) を convmv -f ascii -t utf-8 a.txt --notest
なんて有り得ないわけですよねぇ。
BINARYって判別されたのは 例えば vncviewer.exe とかのファイルです。バイナリファイルだし。。。
この結果を見て私は vncviewer.exe と言うファイル名自体は英数字のみなので ASCIIかと
思いますが、しかしvncviewer.exeのファイルの"中身"はBINARYなので、nkf ってのは
ファイルの中身を見てコードを判別して返してくれるんだなぁと思った次第です。
(nkf がファイル"名"を見て返してくれるのなら vncviewer.exeはBINARYではなくASCIIで
かえって来ないといけないからです。) でも nkf に対して何を入力するかによって
返してくるものは違うんですね。ファイル"名"をnkfに入力すればファイル"名"のコードが帰ってくるし
ファイルの内容を入力すればファイルの内容のコードが帰ってくると。
>>181
度々具体的なスクリプトを示して頂いて本当にありがとうございます。
しかしですね・・・よくエラーを見てみると no such file or directory が帰ってきてるんですよね・・・。
つまり find /data をした結果、文字化けしたファイル名が返ってくるわけじゃないですか。
その文字化けしたファイル名の場合、そのファイルにはアクセスする事が出来ないですよね。
文字化けしたファイルに唯一アクセスする手段があるとすれば、それは "*" を使う事ですよね。
だから for や while で1ファイルずつ処理するっていう最初のアイディア自体がそもそも不可能
だったと言う事に今更ながら気づきました。ほんと文字化け問題って大変ですね・・。
"*"を使うと言っても find /data/* だと結局1ファイルずつ文字化けしたものが帰ってくるので
ダメっぽいです。 convmv に 直接 * を渡す必要があるみたいで、そうすると混在している場合に
全く処理をしてくれなくて結局ダメと。。。参ったなぁ・・・OTL。
それと1つシェルスクリプトスレなのでお聞きしておきたいのですが
File=$( nkf -g <<< "$TARG" ) ←これなんですが、 <<< って何ですか?普通 < か << ですよね。
<<<は初めて

183 名前:165 mailto:sage [2007/09/17(月) 22:30:38 ID:RA5G8Fdp]
>>169
エラーの起こる直前までは変換してくれるのかと思ってた。
いらぬ時間をとらせてすまねぇ。
んで(w)、また懲りずに考えてみたんだが、nkf使うんだったら
find work/ -type f -exec sh -c 'FN="`dirname \"{}\"`"/"`basename \"{}\" | nkf -w`"; [ -f "$FN" ] || mv -v "`echo \"{}\"`" "$FN"' \;
とかいかが?

ディレクトリ含まれてないんだけど、含むと末端からやらないといけないからシェルスクリプトでやるのは面倒くさそうだなァ、と思って逃げたw


184 名前:login:Penguin mailto:sage [2007/09/17(月) 23:04:07 ID:nqz563FT]
>>183
うぐぅ・・・・

そのfind 以下のスクリプト難しすぎて私には何をどうしているのかさっぱり分かりませんです。。
awkとか正規表現とかそこら辺全然知らないので、なんかそれっぽいコードに見えて読めないOTL。

ディレクトリを含まないって言うのも問題ですねぇ・・・。

例えばですが hoge.txt と piyo/ っていうディレクトリが存在していて、それぞれのファイル名
もしくはディレクトリ名の文字コードを知りたい場合はnkfではどのようにコマンド入力したらいいんですか?

ls -d piyo/ | nkf -g
nkf -g < hoge.txt
nkf -g | `ls -d piyo/`
nkf -g <<< hoge.txt
等など色々試してみましたが、文字コードが見えませんでした。

# convmv ももう少し気を利かせて --force オプションなんて作ってくれて処理できないファイルは
スキップして処理可能なファイルだけ全部処理するみたいな機能盛り込んでくれてれば助かったんだけどなぁ・・・。

185 名前:login:Penguin mailto:sage [2007/09/17(月) 23:10:07 ID:kLzbccVO]
無理してシェルで書くより
perl かなんかで書いちゃった方が早い気がする。

186 名前:login:Penguin [2007/09/17(月) 23:26:23 ID:hplwR1nR]
すいません、いろいろやってみたけど出来ないので教えてください。

aaaa,bbbb,cccc,"hoge,hoge",ddd,eee,ffff

みたいなCSVが有ります。
※カンマがある列は必ず「""」で括られています。

# cut -d, -f 4

とかでカンマが含まれる行を出力しようとすると 結果に「"hoge」とのみ出力されてしまいます。
本当は「"hoge,hoge"」が出力されてほしいのです。
「"hoge,hoge"」の出力結果を得るためにはどの様にすれば良いですか?


自分的には、
sedコマンドでいったんワークファイルwor.csvなどに「"hoge\,hoge"」と
エスケープシーケンスを追加してからcutコマンドを実行すればうまく行くような気がしているのですが、
sedをどのように記述して良いのかすら解りません(泣)


どなたか教えてください。。。。

187 名前:login:Penguin mailto:sage [2007/09/17(月) 23:42:08 ID:kUn2DAgf]
実は混在なんかしてない、ていうことはないのんか? もしくはかなり偏っている。
なら、ある程度手作業でその他一括、のが楽かも知れん。

188 名前:login:Penguin mailto:sage [2007/09/17(月) 23:45:48 ID:msAJx7Dr]
結局カンマ関係なしに""で括られたのが欲しいんじゃねぇのか?

189 名前:login:Penguin mailto:sage [2007/09/18(火) 00:04:13 ID:hplwR1nR]
186です。

>>187

1000行近くのCSVファイルで確実に混在しています。
例えば、↓↓↓みたいな行です。
(「US」の後ろにカンマがありますよね?)

75,0,,,-,,-,"LOG3\.0.*123456 .....5.*\(US, 21\): NOTICE:.*",,,,,,,AAAA,BBB,"TEST",WARN,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,1,,,,,,,,,,,,,,,,,,,75


この行から特定の列だけ抜き出し&抜き出しした列を引数にコマンドを実行しています。

>>188

そんなことないです。
実際には初期値の列も多いので。



190 名前:login:Penguin mailto:sage [2007/09/18(火) 00:16:17 ID:u/C4qzX6]
>>182
read に -r オプションつけたらどう?

旧) find /data | while read TARG ; do
新) find /data | while read -r TARG ; do
                 ^^^
> File=$( nkf -g <<< "$TARG" ) ←これなんですが
man bash のヒア・ストリングス (Here Strings) の項を参照。


191 名前:login:Penguin mailto:sage [2007/09/18(火) 00:35:05 ID:u/C4qzX6]
>>189
う〜ん、難しいね。
クォートされたエントリが一行に一つだけなら
↓で取り出すことはできるけど。

sed '/"/ s/.*\(".*"\).*/\1/'

俺なら一度 csv を Excel に放り込んでから
特定の列を抜き出すかな。w






[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<275KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef