Linux에서 파일의 이름과 경로를 포함하는 새 파일을 만듭니다.

Linux에서 파일의 이름과 경로를 포함하는 새 파일을 만듭니다.

fastq.gz내 Linux 시스템의 디렉터리에 R1과 R2라는 여러 파일이 있습니다 . dir다음과 같이 보입니다:

dir
 |____sampleA_1.fastq.gz
 |____sampleA_2.fastq.gz
 |____sampleB_1.fastq.gz
 |____sampleB_2.fastq.gz
 |____sampleC_1.fastq.gz
 |____sampleC_2.fastq.gz

txt첫 번째 열에 샘플 이름, 두 번째 열에 R1 fastq 경로, 세 번째 열에 R2 fastq 경로를 사용하여 파일을 생성하고 싶습니다 .

내부에서는 dir다음을 시도했습니다.

find "$PWD" -name \*1.fastq.gz > list1.txt
find "$PWD" -name \*2.fastq.gz > list2.txt

두 파일을 다시 병합하고 열 이름을 지정하고 예제 이름으로 다른 열을 다시 만들어야 합니다. 대신 단일 명령으로 파일을 만드는 방법이 있습니까?

파일은 txt다음과 같아야 합니다.

sample            Second                    Third
sampleA    dir/sampleA_1.fastq.gz     dir/sampleA_2.fastq.gz
sampleB    dir/sampleB_1.fastq.gz     dir/sampleB_2.fastq.gz
sampleC    dir/sampleC_1.fastq.gz     dir/sampleC_2.fastq.gz

답변1

샘플 쌍이 항상 존재한다고 보장할 수 있는 경우 이 bash/ ksh코드는 모든 샘플 1 파일의 존재를 기반으로 출력을 생성합니다.

예(데모 환경 구축):

mkdir -p /tmp/710303/dir
cd /tmp/710303
touch dir/sample{A,B,C}_{1,2}.fastq.gz       # Assumes a { }-aware shell

파일 생성(데모 환경에서 작동)

printf "%s %s %s\n" 'sample' 'Second' 'Third'
for f1 in dir/sample*_1.fastq*               # Loop through all first samples
do
    fn="${f1##*/}"; fn="${fn%%_*}"           # Label
    f2="${f1/1/2}"                           # Filename for second sample
    printf "%s %s %s\n" "$fn" "$f1" "$f2"    # Output the values
done

산출

sample Second Third
sampleA dir/sampleA_1.fastq.gz dir/sampleA_2.fastq.gz
sampleB dir/sampleB_1.fastq.gz dir/sampleB_2.fastq.gz
sampleC dir/sampleC_1.fastq.gz dir/sampleC_2.fastq.gz

이는 공백으로 구분된 열입니다. 탭으로 구분하려면 (공백) 대신 (탭)을 printf사용하도록 형식 줄을 변경하세요 .\t

답변2

불필요하게 복잡해 보이지만 예제 파일이 하나만 존재하는 상황을 처리하고 있습니다.

{
    printf '%s\n' sample Second Third

    find ./dir/ -type f -name '*.fastq.gz' -print \
    | cut -d _ -f 1 \
    | sort -u \
    | bash -c '
        while read -r root; do
            echo "${root##*/}"
            for i in 1 2; do
                f="${root}_${i}.fastq.gz"
                [[ -f "$f" ]] && echo "$f" || echo ""
            done
        done
      ' 
} \
| paste - - - \
| column -s $'\t' -t

시험:

mkdir dir
touch dir/sample{A,B,C}_{1,2}.fastq.gz
touch dir/sample{D_1,E_2}.fastq.gz
touch dir/ignore.me

그런 다음 위의 명령 출력

sample   Second                    Third
sampleA  ./dir/sampleA_1.fastq.gz  ./dir/sampleA_2.fastq.gz
sampleB  ./dir/sampleB_1.fastq.gz  ./dir/sampleB_2.fastq.gz
sampleC  ./dir/sampleC_1.fastq.gz  ./dir/sampleC_2.fastq.gz
sampleD  ./dir/sampleD_1.fastq.gz  
sampleE                            ./dir/sampleE_2.fastq.gz

어쩌면 이 GNU awk 버전이 좀 더 깔끔할 수도 있습니다.

find ./dir -type f | gawk -F/ -v OFS='\t' '
    BEGIN { print "sample", "Second", "Third" }
    match($NF, /^(.*)_([12]).fastq.gz$/, m) {
        file[m[1]][m[2]] = $0
    }
    END {
        PROCINFO["sorted_in"] = "@ind_str_asc"
        for (sample in file)
            print sample, file[sample][1], file[sample][2]
    }
' | column -s $'\t' -t

위와 동일한 출력을 생성합니다.

답변3

$ cat tst.awk
BEGIN {
    FS="[/_]"; OFS="\t"
    print "sample", "Second", "Third"
}
NR%2 { second = $0; next }
{ print $2, second, $0 }

$ printf '%s\n' dir/* | awk -f tst.awk
sample  Second  Third
sampleA dir/sampleA_1.fastq.gz  dir/sampleA_2.fastq.gz
sampleB dir/sampleB_1.fastq.gz  dir/sampleB_2.fastq.gz
sampleC dir/sampleC_1.fastq.gz  dir/sampleC_2.fastq.gz

관련 정보