Wildcards

連接來自不同目錄的多個文件

  • April 29, 2020

我想連接來自不同目錄的多個文件。

目錄 1:Chr1包含(在此範例中)四個文件:

ABC.1 
DEF.1
GHI.1 
JKL.1 

目錄 2:Chr2

ABC.2  
DEF.2 
GHI.2
JKL.2 

有 22 個目錄。每個文件有 20 列和一個標題。所有文件的標題都相同。

我想將所有文件連接到一個文件中(一個全域輸出文件,用於連接所有目錄中的所有文件)。

我試過這個,但這不起作用。

cat */Chr{1..22}/*.{1..22} > */final_file

它說“沒有這樣的文件或目錄”,因為沒有文件,例如chr22目錄下的文件為*.1~21。

你有什麼想法?先感謝您。

您的方法的問題在於,重複的萬用字元不會以“同步”方式解釋(=“expanded”),而是對於命令行上的每次出現都重新獨立地進行解釋。因此,您將需要使用嵌套的 shell 循環。

您可以嘗試以下 shell 腳本。請注意,它使用bash功能(您的問題不包括您使用的外殼)

#!/bin/bash

hdr=0   # initialize variable to keep track of whether the header is already printed

# loop over directories
for d in Chr*
do
   # extract trailing number from dir name by removing 'Chr' part (bash feature!)
   n="${d#Chr}"

   # loop over all files
   for f in "$d/"*".$n"
   do
      if (( hdr == 0 )) # if header wasn't printed yet, output entire file
      then
          cat "$f" > final_file
          hdr=1
      else              # otherwise, output file content starting with line 2
          tail -n +2 "$f" >> final_file
      fi
   done
done

您可以命名腳本concatenate.sh,使其可執行,然後從所有Chr{1..22}子目錄所在的目錄執行它。也將final_file在該目錄中創建。

請注意,我無法測試它很遠,但它不應該破壞任何東西……

只需使用zsh外殼:

cat -- */Chr<1-22>/*.<1-22>(n) > final_file

In zsh,<x-y>是一個匹配十進制整數範圍的 glob 運算符,並且nglob 限定符切換numericglobsort導致 glob 擴展按數字排序的選項。

在另一個 shell 中,您可以執行以下操作:

zsh -c 'cat -- */Chr<1-22>/*.<1-22>(n) > final_file'

要跳過除第一個文件之外的所有文件的標題,並假設 GNU 或 busybox 實現tail(在使用 Linux 作為核心的系統上最常見),您可以執行以下操作:

(){
 cat < $1; shift; (($#)) && tail -qn +2 -- "$@"
} */Chr<1-22>/*.<1-22>(n) > final_file 

引用自:https://unix.stackexchange.com/questions/583331