根据子字符串匹配对文件进行 cat

根据子字符串匹配对文件进行 cat

我有以下格式的文件名,我想根据子字符串匹配(Orange,Apple)和常量(S4,S5)对文件进行分类,

文件名示例_S6_trimmed_, _S8_trimmed_, _S9_trimmed_, _S10_trimmed_

Orange1_S4_trimmed_1.fastq
Orange1_S4_trimmed_2.fastq
Orange2_S4_trimmed_1.fastq
Orange2_S4_trimmed_2.fastq

Apple1_S4_trimmed_1.fastq
Apple1_S4_trimmed_2.fastq
Apple2_S4_trimmed_1.fastq
Apple2_S4_trimmed_2.fastq

Orange1_S5_trimmed_1.fastq
Orange1_S5_trimmed_2.fastq
Orange2_S5_trimmed_1.fastq
Orange2_S5_trimmed_2.fastq

Apple1_S5_trimmed_1.fastq
Apple1_S5_trimmed_2.fastq
Apple2_S5_trimmed_1.fastq
Apple2_S5_trimmed_2.fastq

我想要做的是对几个样本 S4、S5 重复相同的操作……

cat Orange*_S4_trimmed_1.fastq >Orange_S4_trimmed_1.fastq
cat Orange*_S4_trimmed_2.fastq >Orange_S4_trimmed_2.fastq

cat Apple*_S4_trimmed_1.fastq >Apple_S4_trimmed_1.fastq
cat Apple*_S4_trimmed_2.fastq >Apple_S4_trimmed_2.fastq

这是我在 bash 中编写的脚本,

#!/bin/bash

filename="samples.txt"

while read -r sample;
do
    echo $sample
    cat ${sample}_trimmed_1.fastq >${sample}_trimmed_1.fastq
    cat ${sample}_trimmed_2.fastq >${sample}_trimmed_2.fastq

done <$filename

这是我的 samples.txt 文件的格式,

 samples.txt
 Apple*_S4
 Apple*_S5
 Orange*_S4
 Orange*_S5

有没有更好的方法对一大组文件执行此操作?提前感谢您的帮助。

我目前正在根据 Bodo 上的评论制定解决方案,

#!/bin/bash
    
    for file in *1_*_trimmed_1.fastq;
    do
        echo $file
    
        subs=`echo $file | cut -d_ -f1 | tr -d 0-9`
        echo $subs
    
        sample=`echo $file | cut -d_ -f2`
        echo $sample
    
        cat ${subs}*_${sample}_trimmed_1.fastq >${subs}_${sample}_trimmed_1.fastq
        cat ${subs}*_${sample}_trimmed_2.fastq >${subs}_${sample}_trimmed_2.fastq
    
    done

答案1

1. 将所有源文件粘贴到目标位置

正如您的问题所示,示例代码将文件集的所有文件粘贴到其目标文件中:

#!/bin/sh

destination=""

# Select all source files, but not any existing the destination files:
for file in *[0-9]*_S[0-9]*_trimmed_*[0-9].fastq
do  
    if [ "${destination}" != "${file%%[0-9]*}_${file#*_}" ]
    then
        # Switch to next file set:
        destination="${file%%[0-9]*}_${file#*_}"
        echo "${destination}"
    fi
    # Copy the current source file to destination
    cat "${file}" >"${destination}"
done

这几乎只适用于命名管道作为目标文件,将接收到的数据传输到其他地方。


2. 仅将最后一个源文件粘贴到其目标位置

如果目标是一个常规文件,那么将所有源文件写入目标将是一个巨大的开销,因为内容每次都会被覆盖,只留下最新版本继续保留。

第二种解决方案可避免开销并最大程度地减少要写入的数据量:

#!/bin/sh

destination=""
source=""

# Select all source files, but not any existing the destination files:
for file in *[0-9]*_S[0-9]*_trimmed_*[0-9].fastq
do  
    if [ "${destination}" != "${file%%[0-9]*}_${file#*_}" ]
    then
        if [ "${destination}" != "" ]
        then
            # Not the start situation. Write last file of file set to the destination file:
            cat "${source}" >"${destination}"
        fi
        # Switch to next file set:
        destination="${file%%[0-9]*}_${file#*_}"
        echo ${destination}
    fi
    # Store the current source file name for the next cycle
    source=${file}
done
# Write last source file of the last file set to the destination, if it exists:
if [ "${destination}" != "" ]
then
    cat "${source}" >"${destination}"
fi

正如你用于cat文件复制一样,我也使用了它。但通常人们会改用cp。因此,人们会将行替换cat "${file}" >"${destination}"

cp "${file}" "${destination}"

如果源文件或目标文件不再需要编辑,则应考虑创建硬链接。这样就不会出现数据重复(目标文件不会占用额外的磁盘空间)。只会创建目标文件名,指向与所选源文件相同的数据区域(inode):

cp -l --remove-destination "${file}" "${destination}"

对于大型文件(例如视频数据)来说,这将大大加快速度。

相关内容