フォルダ内のすべてのn番目のファイルをマージして、使用したファイルを削除します。

フォルダ内のすべてのn番目のファイルをマージして、使用したファイルを削除します。

30000個のtxtファイルを含むフォルダがあり、各ファイルのサイズは50-60kbです。 2.5mb txt ファイルにマージする必要があります。そして、マージ中のファイルを削除してください。私のコードは次のようになります。for f in *,50; do cat file1,file2...file49 > somefile.txt;doneもちろんこれは擬似コードです。ファイルを50の束にマージしてから、使用したファイルを削除する必要があります。誰でも私を助けることができますか?

ベストアンサー1

そしてzsh

files=( ./input-file*(Nn.) )
typeset -Z3 n=1
while
 (( $#files > 0 )) &&
   cat $files[1,50] > merged-file$n.txt &&
   rm -f $files[1,50]
do
  files[1,50]=()
  ((n++))
done

./input-file*(Nn.)一致するファイルに展開されますが、./input-file*3つのグローバル修飾子を使用してさらに分類されます。

  • N:nullglob: 一致するものが存在しない場合、エラーによって中断されるのではなく、glob 拡張を null にします。 globで配列を設定するときにこれが必要であり、配列が空であっても大丈夫です。
  • n::numericglobsortデフォルトの語彙ソートを数値ソート(実際には2つの組み合わせ)に変更します。言い換えれば、input-file2フロントソートです。input-file10
  • .: 限定定期的なファイル(ディレクトリ、シンボリックリンク、FIFOを無視...)

typeset -Z3 n$n幅が3になるまで変数を0で埋めて、次のようにしますmerged-file001.txt。 ... merged-file049.txt...

次に、配列に要素があり、エラーがない限り、$files一度に50のバッチ(および最後のバッチで残っているすべての要素)を連結して繰り返します。

bash 4.4+およびGNUツールにも同じことが当てはまります。

readarray -td '' files < <(
  LC_ALL=C find . -maxdepth 1 -name 'input-file*' -type f -print0 |
    sort -zV
)
n=0
set -- "${files[@]}"
while
 (( $# > 0 )) &&
   printf -v padded_n %03d "$n" &&
   cat "${@:0:50}" > "merged-file$padded_n.txt" &&
   rm -f "${@:0:50}"
do
  shift "$(( $# >= 50 ? 50 : $# ))"
  ((n++))
done

findzshが機能している場合、./input-file*(N.)数値sort -V(バージョン)ソートは位置引数を使用し、配列は非常に制限されているため、shiftループ内で配列を使用します。bash

おすすめ記事