リストから i 番目の要素から j 番目の要素まで、n 番目の要素までの範囲の要素を抽出します。

リストから i 番目の要素から j 番目の要素まで、n 番目の要素までの範囲の要素を抽出します。

ディレクトリには、一定数のファイルがあります。53 個の txt ファイルの場合もあれば、123 個のファイルの場合もあり得ます。ファイルにはさまざまなランダムな名前が付けられていますが、すべてファイル ハンドルが付けられています。.txt

ls を使用してすべてのファイルのリストを取得し、これを変数に格納できます。

list_of_txt_files=$(ls *.txt)

しかし、リストを複数の個別のリストに分割し、各リストに 10 個の要素のみを含めたいと考えています。つまり、53 個の txt ファイルを含むフォルダーの場合は、6 つのリストを作成する必要があります。つまり、10 個のファイル名を含む 5 つのリストと、3 個のファイル名を含む 6 番目のリストです。また、ディレクトリに 123 個の txt ファイルがある例では、10 個のファイル名を含む 12 個のリストと、3 個のファイル名のみを含む 13 番目のリストを作成する必要があります。

53 個の txt ファイルがある私の例では、リスト 1 には最初のファイルから 10 番目のファイルまでが保持され、リスト 2 には 11 番目のファイルから 20 番目のファイルまでが保持されます。以下同様に続きます。他の人はリストを別の方法で分類するかもしれないので、質問にリスト内の i 番目から j 番目の要素というタイトルを付けました。おそらく、ディレクトリ内の最初のファイルから 100 番目のファイルまででしょう。

最終的な目標は、これらのリストを for do ループで使用し、cat コマンドを使用して、リストごとに 10 個のファイルの内容を 10 個のファイル セットごとに 1 つのファイルに書き出すことです。つまり、ディレクトリに 53 個のファイルがある私の例では、6 つのファイルが作成されます。最初の 5 つのファイルには、元の 50 個の txt ファイルの内容が含まれ、6 番目のファイルには、残りの最後の 3 つの txt ファイルの内容が含まれます。

head コマンドまたは tail コマンドの使用を検討しましたが、これら 2 つのコマンドの範囲を指定する方法がわかりません。

答え1

シェルに配列それらを使用します。Bash で言うと:

$ touch {01..53}
$ files=(*)
$ echo "${files[@]:0:10}"       
01 02 03 04 05 06 07 08 09 10

$ for ((i = 0 ; i < ${#files[@]} ; i += 10 )) ; do
     echo "${files[@]:i:10}" ; 
     # or
     # cat "${files[@]:i:10}" > set-$(( i / 10 ))
  done
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53

部分文字列の拡張(配列スライス) は"${files[@]:i:10}"単一の文字列ではなく単語のリストに展開されるため、ループすることができます。

for f in "${files[@]:i:10}" ; do
    somecmd "$f"
done

しないでくださいを実行するとfiles=$(ls *.txt)lsは完全に冗長になります。ワイルドカードを評価するのはシェルです。通常は、ワイルドカード パターンを変数 ( pat=*.txt) に保存し、必要な場所で (引用符なしで) 使用するか、実際のファイル名に展開する場合は、echo *.txtの代わりにを使用しますls。ファイル名のリストを処理する場合、プレーンな POSIX シェルに制限されていない限り、配列の方が適しています。


headとを使用してリストを分割する場合は、 11 行目から 20 行目を取得するために、tail次のような操作を行う必要があります。または、sed: を使用します。| head -20 | tail -10| sed -n 11,20p

答え2

任意の Bourne のようなシェル (ただし、 上の位置要素にアクセスできない Bourne シェル$9) を使用すると、次の操作を実行できます。

set -- *.txt
while [ "$#" -gt 0 ]; do
  something with "$1" ${2+"$2"} ${3+"$3"}... ${10+"${10}"}
  [ "$#" -gt 10 ] || break
  shift 10
done

GNUxargsとプロセス置換をサポートするシェルの場合:

xargs -n10 -r0a <(printf '%s\0' *.txt) something with

zsh

files=(*.txt(N))
while (($#files)) {
  something with $files[1,10]
  files[1,10]=()
}

または:

autoload -U zargs
xargs -l10 -- *.txt -- something with

zshまた、のグロブでは範囲を使用できることにも注意してください。

something with *.txt([1,10])

関連情報