4

私は現在、数学プロジェクトに取り組んでおり、bash でのプログラミングで少しレンガの壁にぶつかっています。

現在、800 個のテキスト ファイルを含むディレクトリがあり、ループを実行して最初の 80 個のファイル ( _01から _80 まで) を新しいファイルに分類し、別の場所に保存してから、次の 80 個の (_81 から _160) ファイルを保存します。等

ディレクトリ内のすべてのファイルは、ath_01、ath_02、ath_03 などのようにリストされます。

誰でも助けることができますか?

これまでのところ、私は持っています:

#!/bin/bash

for file in /dir/*

do
echo ${file}
done

私のファイルを簡単にリストします。どういうわけか cat file1 file2 > newfile.txt を使用する必要があることはわかっていますが、_01、_02 などの番号付き拡張子と混同しています。

ファイルの名前をアンダースコア以外のものに変更すると役に立ちますか? ath.01など?

乾杯、

4

4 に答える 4

5

持っているファイルの数と番号の付け方を事前に知っているので、いわば「ループを展開」し、コピーアンドペーストと少し手作業で調整して、次のようなスクリプトを作成する方が簡単な場合があります。ブレース展開を使用します。

#!/bin/bash

cat ath_{001..080} > file1.txt
cat ath_{081..160} > file2.txt
cat ath_{161..240} > file3.txt
cat ath_{241..320} > file4.txt
cat ath_{321..400} > file5.txt
cat ath_{401..480} > file6.txt
cat ath_{481..560} > file7.txt
cat ath_{561..640} > file8.txt
cat ath_{641..720} > file9.txt
cat ath_{721..800} > file10.txt

または、ネストされたforループとseqコマンドを使用します

N=800
B=80
for n in $( seq 1 $B $N ); do
    for i in $( seq $n $((n+B - 1)) ); do
       cat ath_$i
    done > file$((n/B + 1)).txt
done

外側のループは1、81、161nなどを繰り返します。内側のループはi1から80、次に81から160などを繰り返します。内側のループの本体は、ithファイルが標準出力の場合に内容をダンプしますが、ループの集約された出力は、ファイル1、次に2などに格納されます。

于 2013-03-03T16:58:08.123 に答える
4

次のようなことを試すことができます:

cat "$file" >> "concat_$(( ${file#/dir/ath_} / 80 ))"
  • ファイル名から${file#/dir/ath_}プレフィックスを削除すると/dir/ath_
  • $(( / 80 ))80(整数除算)で割った接尾辞を取得します

また、ループを次のように変更します

for file in /dir/ath_*

そのため、必要なファイルのみを取得できます

于 2013-03-03T15:18:22.253 に答える
3

80 個のファイルのグループが必要な場合は、名前が並べ替え可能であることを確認するのが最善です。そのため、先行ゼロがよく使用されていました。ファイル名にアンダースコアが 1 つしかなく、名前に改行がないと仮定すると、次のようになります。

SOURCE="/path/to/dir"
TARGET="/path/to/other/directory"
(
cd $SOURCE || exit 1
ls |
sort -t _ -k2,2n |
awk -v target="$TARGET" \
    '{ file[n++] = $1
       if (n >= 80)
       {
           printf "cat"
           for (i = 0; i < 80; i++)
               printf(" %s", file[i]
           printf(" >%s/%s.%.2d\n", target, "newfile", ++number)
           n = 0
       }
     END {
       if (n > 0)
       {
           printf "cat"
           for (i = 0; i < n; i++)
               printf(" %s", file[i]
           printf(" >%s/%s.%.2d\n", target, "newfile", ++number)
       }
     }' |
sh -x
)

2 つのディレクトリが指定されています (ファイルの場所とサマリーの場所)。このコマンドは、ディレクトリをソース ディレクトリ (800 個のファイルがある場所) に変更します。名前を一覧表示し (必要に応じて glob パターンを指定できます)、数値順に並べ替えます。出力はawk、オンザフライでシェル スクリプトを生成する に渡されます。一度に 80 個の名前を収集し、catそれらのファイルを .xml などの単一の宛先ファイルにコピーするコマンドを生成し"newfile.01"ます。printf()独自の命名/番号付け規則に合わせてコマンドを微調整してください。シェル コマンドは、実行のためにシェルに渡されます。

テスト中は、sh -xを何も置き換えないか、またはsh -vn同様のものに置き換えます。必要なことが確実に実行される場合にのみ、アクティブなシェルを追加してください。シェル スクリプトは実行中のソース ディレクトリにあることに注意してください。

表面的には、このxargsコマンドは使いやすいものです。問題は、出力ファイル番号を調整することです。一度に 80 個のファイルをグループ化するオプションと呼び出し番号を生成するための凝った方法でそれを行う方法があるかもしれませんが、-n 80私はそれを認識していません。

もう 1 つのオプションはxargs -n、シェル スクリプトを実行するために使用することです。シェル スクリプトは、ターゲット ディレクトリに既にあるものを一覧表示することにより、正しい出力ファイル番号を推測できます。これは多くの点でよりクリーンになります。

SOURCE="/path/to/dir"
TARGET="/path/to/other/directory"
(
cd $SOURCE || exit 1
ls |
sort -t _ -k2,2n |
xargs -n 80 cpfiles "$TARGET"
)

cpfilesのようになります。

TARGET="$1"
shift
if [ $# -gt 0 ]
then
    old=$(ls -r newfile.?? | sed -n -e 's/newfile\.//p; 1q')
    new=$(printf "%.2d" $((old + 1)))
    cat "$@" > "$TARGET/newfile. $new
fi

ゼロ引数のテストは、ゼロ引数xargsでコマンドを 1 回実行する際の問題を回避します。全体として、私は を使用するソリューションよりもこのソリューションを好みawkます。

于 2013-03-03T15:31:24.387 に答える
1

GNU Makeテンプレート言語として使用する @chepner の最初のソリューションのマクロを次に示します。

SHELL := /bin/bash
N = 800
B = 80

fileNums = $(shell seq 1 $$((${N}/${B})) )
files = ${fileNums:%=file%.txt}

all: ${files}

file%.txt : start = $(shell echo $$(( ($*-1)*${B}+1 )) )
file%.txt : end = $(shell echo $$(( $* * ${B} )) )

file%.txt:
        cat ath_{${start}..${end}} > $@

使用するには:

$ make -n all
cat ath_{1..80} > file1.txt
cat ath_{81..160} > file2.txt
cat ath_{161..240} > file3.txt
cat ath_{241..320} > file4.txt
cat ath_{321..400} > file5.txt
cat ath_{401..480} > file6.txt
cat ath_{481..560} > file7.txt
cat ath_{561..640} > file8.txt
cat ath_{641..720} > file9.txt
cat ath_{721..800} > file10.txt
于 2013-03-06T01:05:00.337 に答える