동일한 접미사가 있는 여러 디렉터리를 반복한 다음 그 안에 있는 특정 파일에 대해 함수를 실행하는 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
glob
vs ( 여기서 사용함) 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
각 출력 파일을 차례로 구성할 수 있습니다.