提取清單中從第 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 將保留第一個文件直到第十個文件,並列出 no。 2 將保存第十一個文件到第二十個文件,依此類推。我將我的問題從清單中的第 i 個元素命名為第 j 個元素,因為我想其他人可能想要以不同的方式分解清單。也許從目錄中的第一個檔案到第 100 個檔案。

最終目標是能夠在for do 循環中使用這些列表,並使用cat 命令,將每個列表的10 個文件的內容寫到每組10 個文件的一個文件中- 即在我的示例中,有53 個文件一個目錄,這會給我 6 個文件。其中前 5 個檔案包含 50 個原始 txt 檔案的內容,第 6 個檔案包含最後剩餘 3 個 txt 檔案的內容。

我考慮過使用 head 或 tail 命令,但無法完全弄清楚如何指定這兩個命令的範圍。

答案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

do files=$(ls *.txt)ls在那裡完全是多餘的,無論如何,shell 都會評估通配符。通常,您只需將通配符模式保存到變數 ( pat=*.txt) 並在需要時使用它(不含引號),或者如果您想將其擴展為實際文件名,請echo *.txt使用ls.對於處理檔案名稱列表,如果您不限於普通的 POSIX shell,那麼數組會更好。


至於用headand分割列表tail,您需要執行類似取得| head -20 | tail -10第 11 行到第 20 行的動作。| sed -n 11,20p

答案2

使用任何類似 Bourne 的 shell(但 Bourne shell 無法透過 存取位置元素$9),您可以執行以下操作:

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

xargs使用支援進程取代的GNU和 shell:

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另請注意,您可以在 的 glob中使用範圍:

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

相關內容