誰能幫我解決以下問題?我有大約 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 選項,但這會使腳本稍微短一些。您想要確保您的全域模式不太寬泛,因此您告訴
cat
輸入和輸出使用相同的檔案名,如果您這樣做,當您嘗試建立無限大小的檔案時,您可能會很快填滿硬碟。如果您給出類似的模式
*.fasta
,但它不匹配任何文件,則*.fasta
使用文字字串。如果您有一個名為的文件
*.fasta
,那麼區分該文件與模式之間的差異的一種方法是查看它是否可讀。--
如果可能存在惡意檔案名,那麼結束參數解析是個好主意。
首先是一個簡單的腳本。
# 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