유닉스. 경로 이름에 정규 표현식이 있는 특정 파일에 대해 여러 디렉터리에서 스크립트 실행

유닉스. 경로 이름에 정규 표현식이 있는 특정 파일에 대해 여러 디렉터리에서 스크립트 실행

동일한 접미사가 있는 여러 디렉터리를 반복한 다음 그 안에 있는 특정 파일에 대해 함수를 실행하는 bash 스크립트(split.sh)를 만들고 싶습니다. 나는 곧 도착할 것이다:

#!/bin/bash
path="/mypath/MAP-9-[0-9][0-9][0-9]"

for filename in $path/*bam; do
    [ -e "$filename" ] || continue
    echo $filename
        for chrom in `seq 1 22` X Y
        do
        samtools view -bh $filename $chrom > $path/$chrom.bam
        samtools index > $path/$chrom.bam; 
        done
done

그러나 다음과 같은 메시지가 많이 표시됩니다. "split.sh: line 12: /mypath/MAP-9-[0-9][0-9][0-9]/6.bam: No such file or Directory "

문제는 스크립트가 경로 이름의 "[0-9][0-9][0-9]" 정규식 부분을 인식하지 못한다는 것입니다. 또한 대괄호 안에 이스케이프 문자를 추가하려고 시도했지만 성공하지 못했습니다. 이것은 매우 간단한 해결책임에 틀림없지만, 나는 그것을 알아낼 수 없습니다.

다음은 tree 명령 출력에서 ​​발췌한 내용입니다.

|-- [[
|-- MAP-9-001
|   |-- MAP-9-001.bam
|   `-- MAP-9-001.bam.bai
|-- MAP-9-003
|   |-- MAP-9-003.bam
|   `-- MAP-9-003.bam.bai
|-- MAP-9-005
|   |-- MAP-9-095.bam
|   `-- MAP-9-095.bam.bai
|-- split.sh

답변1

globvs ( 여기서 사용함) regex와 혼동하지 마세요 .glob

Glob은 문자열이나 확장된 경로 이름을 일치시키는 데 사용할 수 있는 셸 패턴입니다.

[[ $name = Bob* ]]
rm *.txt

바라보다http://mywiki.wooledge.org/glob

수정된 스크립트 버전:

#!/bin/bash

for filename in /path/MAP-9-[0-9][0-9][0-9]/*bam; do
    [[ -e $filename ]] || continue
    echo "$filename"
    for chrom in {1..22} X Y; do
        samtools view -bh "$filename" "$chrom" > "$(dirname "$filename")/$chrom.bam"
        samtools index "$(dirname "$filename")/$chrom.bam"
    done
done

쉘에서 올바르게 인용하는 방법을 배우는 것은 매우 중요합니다.

공백/메타 문자를 포함하는 모든 리터럴은 "큰따옴표"로 처리합니다.모든확장: "$var", "$(command "$var")", "${array[@]}", "a & b". 'single quotes'코드나 텍스트 $'s: 'Costs $5 US'에 대해서는 ssh host 'echo "$HOSTNAME"'을 참조하십시오.
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words
언제 큰따옴표가 필요합니까?


[[[명령 과 유사하지만 더 강력한 bash 키워드입니다 . 바라보다http://mywiki.wooledge.org/BashFAQ/031그리고http://mywiki.wooledge.org/BashGuide/TestsAndConditionals. POSIX sh에 글을 쓰는 것이 아니라면 추천합니다.[[

답변2

/mypath/MAP-9-[0-9][0-9][0-9]/*.bam쉘 글로브이거나파일 이름 확장자표현하다. 이는 일치하는 파일 목록으로 확장됩니다. 이를 사용하여 입력 파일을 반복할 수 있지만 해당 출력 파일을 생성하기 위해 "모든 반복" 와일드카드로 간주할 수는 없습니다. 아마도 당신이 원하는 것은 $filename다음과 같이 해당 루프 변수에서 각 출력 파일을 생성하는 것입니다.

#!/bin/bash

shopt -s nullglob

for filename in /mypath/MAP-9-[0-9][0-9][0-9]/*.bam; do
    [ -e "$filename" ] || continue
    echo "$filename"
    for chrom in {1..22} X Y; do
        samtools view -bh "$filename" "$chrom" > "${filename%/*}/${chrom}.bam"
        samtools index > "${filename%/*}/$chrom.bam"
    done
done

껍데기매개변수 확장 ${filename%/*}의 값으로 확장 $filename하고 가장 짧은 후행 하위 문자열을 제거하므로 /*각 입력 파일의 디렉터리 이름이 제공되며, 이를 추가하여 $chrom.bam각 출력 파일을 차례로 구성할 수 있습니다.

관련 정보