Cat

將來自不同目錄的類似名稱的文件轉換為具有相同名稱的單個文件

  • April 2, 2020

誰能幫我解決以下問題?我有大約 40 個不同物種的目錄,每個目錄都有 100 個包含直系同源序列的序列文件。每個物種目錄的序列文件都以類似的方式命名。我想將 40 個物種目錄的同名文件連接到一個名稱相似的序列文件中。

例如,我有以下 3 個目錄:“Species1”、“Species2”、“Species3”。在這些目錄中有類似命名的文件:“SequenceA.fasta”、“SequenceB.fasta”、“SequenceC.fasta”。我需要將不同 SequenceA.fasta 文件的所有內容連接到另一個目錄中名為“SequenceA.fasta”的新文件中。我該怎麼做呢?

我嘗試了以下循環,但失敗了。文件已創建但為空:

ls . | while read FILE; do cat ./*/"$FILE" >> ./final/"$FILE"; done

感謝您的任何建議或幫助!

(抱歉任何可能的交叉發帖,我之前不小心在錯誤的論壇上發布了這個問題)

這個答案有幾點需要注意。

  1. ls如果您可以改為使用 shellglob模式來做您想做的事情,解析輸出通常是一個壞主意- 請參閱 [ http://mywiki.wooledge.org/ParsingLs]。我沒有使用 nullglob shell 選項來實現可移植性,但這會使腳本稍微短一些。
  2. 您希望確保您的 glob 模式不會太寬泛,因此您告訴cat輸入和輸出使用相同的文件名,如果這樣做,您可能會在嘗試創建無限大小的文件時非常快地填滿硬碟驅動器。
  3. 如果您給出類似的模式*.fasta並且它不匹配任何文件,則使用文字字元串*.fasta
  4. 如果你有一個名為的文件,*.fasta那麼區分它和模式的一種方法是查看它是否可讀。
  5. --如果可能存在惡意文件名,則結束參數解析是一個好主意。

首先是一個簡單的腳本。

# Simple script, assumes that "Species1" has all the needed "SequenceX.fasta" files
# Start in the directory containing "Species1", "Species2" etc.
# create output directory
mkdir "final"
# Go into the first directory
cd "Species1"
# Loop over all the files
for i in *".fasta"
do
   # join all the like named files in the sibling directories to the output
   # use a pattern which doesn't match ../final/$i to get list of files to join.
   cat "../Species"*"/$i" > "../final/$i"
done

這假定“Species1”具有所有“SequenceX.fasta”文件。如果不是這種情況,那麼您可能需要一個雙循環。這更健壯但更長更慢。

# Start in the top level and loop over the directories
for dir in */
do
   # don't do anything inn the output directory
   [ "$dir" = "final" ] && continue
   # cd into directory, protecting against rogue directory names
   cd "./$dir" || { echo "cd to $dir failed" >&2 ; exit 1 ; }
   # loop over the files 
   for file in *"fasta"
   do
        # check the file exists, if there are no files matching the pattern
        # then the shell will pass the pattern through to the loop
        if [ -r "$file" ] ; then
            cat -- "$file" >> "../final/$file"
        fi
   done
   cd ".." || { echo "failed to return from $dir" ; exit 1 ; }
done

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