2017-05-05 50 views
0

在我的目錄我有文件(* fastq.gz.fasta)和目錄,名​​稱中包含文件名(* fastq.gz.fasta-blastdb):擊(分)文件名比較失敗

IVC6_Meino.clust.gz.fasta-blastdb 
IVC5_Mehiv.clust.gz.fasta-blastdb 
.... 
IVC6_Meino.clust.gz.fasta 
IVC5_Mehiv.clust.gz.fasta 
.... 

在bash腳本中,我想比較文件名和直接使用後者的cut選項來提取文件名部分。如果這兩個名字匹配,我想做更多的事情(現在回聲匹配或不匹配)。 我寫了下面的一段代碼:

#!/bin/bash 

for file in *.fasta 
do 
    for db in *-blastdb 
    do 
     echo $file, $db | cut -d '-' -f 1 
     if [[ $file = "$db | cut -d '-' -f 1" ]]; then 
      echo "match" 
     else 
      echo "no match" 
     fi 
    done 
done 

但它不能檢測匹配。輸出看起來是這樣的:
...

IVC6_Meino.clust.gz.fasta, IIIA11_Meova.clust.gz.fasta 
no match 
IVC6_Meino.clust.gz.fasta, IVC5_Mehiv.clust.gz.fasta 
no match 
IVC6_Meino.clust.gz.fasta, IVC6_Meino.clust.gz.fasta 
no match 

最後一行應閱讀比賽,你可以看到,該字符串看起來是一樣的。 我錯過了什麼?

回答

0

您可以使用parameter expansion這更容易做到:

for file in *.fasta 
do 
    for db in *-blastdb 
    do 
     echo "$file", "$db"   
     if [[ "${file%%.fasta}" = "${db%%.fasta-blastdb}" ]]; then 
      echo "match" 
     else 
      echo "no match" 
     fi 
    done 
done 

如果你想解決你的問題是使用的$db | cut -d '-' -f 1隨着echo出現echo正在打印的管道。事實並非如此。正在打印cut。當你做[[ $file = "$db | cut -d '-' -f 1" ]]它相當於[[ $file = [return code from last pipe component] ]]

您需要使用$(..)殼構造捕捉管的輸出,你需要echo得到的$db內容來啓動管道。你應該引用"$db",所以你沒有從變量的內容中分詞或匹配。

像這樣:

for file in *.fasta 
do 
    for db in *-blastdb 
    do 
     ts=$(echo "$db" | cut -d '-' -f 1) 
     echo "$file", "$ts" 
     if [[ "$file" = "$ts" ]]; then 
      echo "match" 
     else 
      echo "no match" 
     fi 
    done 
done    # this works I think -- not tested... 

請小心用砸向你報價和自由的使用ShellCheck


你有的結構也不是最有效的。對於*-blastdb中的每個文件,您將遍歷*-blastdb glob一次。如果你有很多文件,那可能會很慢。

爲了解決這一點,你可以重寫該環路與擊陣列(最好,如果你有擊4+)或使用awk

ext1=.fasta 
ext2=.fasta-blastdb 
awk 'FNR==NR{ 
       s=$0 
       sub("\\"ext1"$","",s) 
       seen[s]=$0 
       next} 
       { 
       s=$0 
       sub("\\"ext2"$","",s) 
       if (s in seen) 
       print seen[s], $0 
       } 
       ' ext1="$ext1" ext2="$ext2" <(for fn in *$ext1; do echo "$fn"; done) <(for fn in *$ext2; do echo "$fn"; done) 

每個水珠僅執行一次,並且awk是使用陣列來測試如果基名是相同的。

最好