アプリ版:「スタンプのみでお礼する」機能のリリースについて

file.1 file.2 ..... file.xx とxxが連番になっている複数のテキストファイルがあります。
これを1つのファイル"file.all"にするために以下のシェルスクリプトを作ってみました。
(公開するのも恥ずかしいのですが...^ ^;)

#!/bin/sh
i=1
while [ $i -le 99 ];
do
 cat file.$i >> file.all
 let i=i+1
done

これだと99までのファイルしか指定できません。
99999...とループ回数を増やせばいいのですが、
それよりももっとスマートにやる方法があるのではと思い質問を投稿いたしました。
シェルスクリプトではなくコマンドによる方法でも結構です。
(RH7.3を使っています)
よろしくお願いします。

A 回答 (10件)

>file.20 file.19 file.18....file.1 といった感じで結合しなくてはいけませんでした。


>このfile.xxの最大値は決まっていないのでどうにかして取得する必要がありますが

最大値取るの結構面倒ですね。。。
取る方法としては一度ループして数えるってのが一番簡単かな。。
あとはawkとsed使えばできると思います。

ここは発想の転換でこんな感じでどうでしょう?
読込むファイル先頭に追加していけば
file.1,file.2・・とやっても結果はfile.20 file.19 file.18....file.1
と同じになるので最大値を取得する必要がありません。

#!/bin/sh

iCnt=1
iLoop=1
LoopCnt=`ls -l file.[0-9]* | wc -l`

while [ $iLoop -le $LoopCnt ]
do
  if [ -f file.$iCnt ]
  then
   cat -s file.$iCnt file.all > file.work
   mv file.work file.all
   let iLoop=iLoop+1
  fi
  let iCnt=iCnt+1
done
    • good
    • 0
この回答へのお礼

何度もご回答ありがとうございます!

>ここは発想の転換でこんな感じでどうでしょう?
>読込むファイル先頭に追加していけば
>
きましたね!こういった発想のできる頭が欲しいです!
あとそれを実行できるテクニックが...

>cat -s file.$iCnt file.all > file.work
>mv file.work file.all
>
アイデアが出ても、これが思いつかないんです...^ ^;;
勉強になります!

お礼日時:2003/04/25 15:00

#8 訂正


わざわざsort -r使わなくても ls -r でできましたね(^^;
ついでに、3桁まで対応させます。
この一行を置き換えてください。

filenames="`ls -r f.[0-9][0-9][0-9]` `ls -r f.[0-9][0-9]` `ls -r f.[0-9]`"

ファイルのワイルドカードでの表現がわっていれば、
簡単に増やせます。
[0-9]の部分が0から9の範囲での任意の一文字という意味になってます。
[0-9][0-9]とかけば、それが二つ分。
    • good
    • 0
この回答へのお礼

補足ありがとうございました。

例と説明もありがとうございました。
>わざわざsort -r使わなくても ls -r でできましたね(^^;
>
すばらしいです!かなり見やすくなりました。

今回はme_no_carさんのスクリプトを使わせて頂きましたが、
terra5さんの考え方も今後必ず役に立つと思っております。
少なくとも'[0-9]'のマッチングの使い方がわかりやすく理解できなので、かなりの収穫です!

ありがとうございました!

お礼日時:2003/04/28 09:03

#4の補足



あれだけわかれば後は大丈夫かと手抜きしたんですが(^^;

例えば,
`ls f.[0-9]` `ls f.[0-9][0-9]`
とすれば、最初ので f.0 ~ f.9 次の出 f.00~f.99がマッチしますのでうまくいきます。
前の回答はsort入れてましたが、lsの出力はソート済みなので不要ですね。

逆順だとソートが必要で、例えば0~99なら

cat `ls f.[0-9][0-9] | sort -r` `ls f.[0-9] | sort -r` >f.all

こんな感じで。
でも、10000もあると一回ではコマンドラインの制限越えそうなのでこのままでは多分無理ですね。
一行ではかきづらくなったのでスクリプトにすると、

filenames="`ls f.[0-9][0-9] | sort -r` `ls f.[0-9] | sort -r`"
rm -f f.all
for fname in $filenames
do
cat $fname >> f.all
done

ではどうですか。

最初に存在するファイルのリストを変数filenamesに設定し、for でリストから一つづづ名前を取り出しています。
    • good
    • 0
この回答へのお礼

再度補足のアドバイスありがとうございます!

>あれだけわかれば後は大丈夫かと手抜きしたんですが(^^;
>
すみません...基本が全然なので、応用が利かないんです^ ^;;
基本勉強の大切さを痛感いたしました。

> (snip)
>ではどうですか。
もうばっちりでした!
後は10桁ほどの数字にも対応できるようにアイデアを考えるだけですが、
またそこで自分の頭の固さが...うぅぅ

今回はみなさんの良きアドバイスのおかげで
かなりアイデアの幅が広がったような気がします!
ありがとうございました!

お礼日時:2003/04/25 14:18

ごめんなさい。



>iLoop=LoopCnt1
>この部分は
>iLoop=$LoopCntですか?

仰る通りです。タイプミスです。
    • good
    • 0

#5のme_mo_carさんのモデファイすれば、OKですよ。



#!/bin/sh

iCnt=1
LoopCnt=`ls -l file.[0-9]* | wc -l`
iLoop=LoopCnt1

while [ $iLoop -le $LoopCnt ]
do
 if [ -f file.$iCnt ]
 then
  cat file.$iCnt >> file.all
  let iLoop=iLoop+1
 fi
 let iCnt=iCnt-1
done
て具合です。ポイントはme_no_catさんへお願いします。

この回答への補足

アドバイスありがとうございます。
すみません。
 iLoop=LoopCnt1
この部分は
 iLoop=$LoopCnt
ということでしょうか?
この部分が不明だったので試していませんが、
これだとfile.xxのxxが最大のファイル名が取得できないような気がするのですが...。
どうでしょうか?

補足日時:2003/04/24 18:32
    • good
    • 0

普通は#4さんみたいな方が一般的なのかなって


思います。
その為にファイル名例えば
file.0001
file.0002
とかってすればそのまま使えます。


とりあえず今回のこんな感じでどうでしょ。
---------------------------------
#!/bin/sh

iCnt=1
iLoop=1
LoopCnt=`ls -l file.[0-9]* | wc -l`

while [ $iLoop -le $LoopCnt ]
do
 if [ -f file.$iCnt ]
 then
  cat file.$iCnt >> file.all
  let iLoop=iLoop+1
 fi
 let iCnt=iCnt+1
done

この回答への補足

できた!と思って出来たファイルを見たところ重要なことに気が付きました。
ファイルの結合順序が逆だったのです。
file.1 file.2 file.3... ではなく
file.20 file.19 file.18....file.1 といった感じで結合しなくてはいけませんでした。
このfile.xxの最大値は決まっていないのでどうにかして取得する必要がありますが
その方法が思いつきません。
今回は大きくても10000くらいなので、そこから逆に file -fで探すという方法があると思いますが、
それしか無いのでしょうか?
できれば最大値が10桁くらいの数になっても対応できるようにしたいです。

みなさんすみません、ガチガチ頭の私に知恵をかしてください!

補足日時:2003/04/24 17:45
    • good
    • 0
この回答へのお礼

ありがとうございます!
完璧です!

自分もme_no_carさんのような柔軟な頭が欲しいです...^ ^;;

みなさんありがとうございました!

お礼日時:2003/04/24 17:27

実在するファイルに関して処理すればいいなら、


ファイルのマッチングを使い,全て引数にしてcatに渡せばカウントする必要はないですね。

例えば,

cat `ls file.* | sort` >file.all

ファイル名を数字に限定したければ、*を適当に置き換える。
例えば,

cat `ls file.[0-9]* | sort` >file.all

実は、このままだと問題があります(^^;
file.1 file.10 file.11 file.2 というような順番になりますから。
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます!

>実は、このままだと問題があります(^^;
>file.1 file.10 file.11 file.2 というような順番になりますから。
>
すみません、実はこれが許されないので...

ですが、ファイルのマッチングでの処理には興味があります。
うまく処理できるようなマッチング方法があればいいのですが...。
自分の頭ではterra5さんの方法以外思いつかないです..^ ^;;

お礼日時:2003/04/24 15:06

私なら、最初のファイル名(数字部分を除いた)を引数にし、ディレクトリ内の同形式ファイルの数を数え、ファイル数でループし、読み出したファイルを順につないでいきます。

この回答への補足

アドバイスありがとうございます。

>私なら、最初のファイル名(数字部分を除いた)を引数にし、
>ディレクトリ内の同形式ファイルの数を数え、ファイル数でループし、読み出したファイルを順につないでいきます。
>
#2の方の実践的な例ですね。

これを書いていて気づいたのですが、file.xxのxxは実は連番ではなく、抜けもあるようです。
なのでxxはfile.xxの総数にはならないようです。
なので、xxの最大の数を求めるといった仕組みが必要になりそうです。
ん~自分の頭の中では、かなり複雑な処理になってしまうのですが...。
何か良い案があったら補足願います!

補足日時:2003/04/24 13:12
    • good
    • 0
この回答へのお礼

みなさん、すみません!
条件に誤りがありました!

ここの補足に記載いたしました。

お礼日時:2003/04/24 13:18

実際にシェルスクリプトなるもののソースコードをだしなさいと言われると困ってしまうのですが、アルゴリズム的にこんなのはどうでしょうか?


雰囲気だけと思って下さい。デバックはしてません。

(1) filenum=`ls -l /filedir/ |wc -l`
let filenum=filenum - 2(余計な行分だけ引いてください)
こんな感じでファイル数を取得

(2) 後は、tk1224さんのソースコードのi=1を
i=filenumと書き換えてあげれば・・・

どうでしょうか?
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます!

>(1) filenum=`ls -l /filedir/ |wc -l`
>let filenum=filenum - 2(余計な行分だけ引いてください)
>
なるほど、雰囲気はつかめました。
後は確実にファイル数を把握するような処理を加えていくといった感じですね。

ありがとうございました。

お礼日時:2003/04/24 13:09

シェルスクリプトなら、こんなもんでしょう。



ただ、わたしなら、ループの回数を引数にしますね。
    • good
    • 0
この回答へのお礼

早速のアドバイスありがとうございます!

>シェルスクリプトなら、こんなもんでしょう。
>
そうなんですか?
ということはシェル以外で対応する ということでしょうか?

>ただ、わたしなら、ループの回数を引数にしますね。
>
とりあえず全自動のスクリプトなので、ファイル数をカウントする処理が必要になりますね。

お礼日時:2003/04/24 13:07

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!