for 루프 단순화

for 루프 단순화

아래의 for 루프를 이해하고 단순화하고 싶습니다. 예를 들어 디렉터리의 각 예제에 대한 rem 파일을 연결하고 싶습니다.

문서:

file1.1.fq
file1.rem.1.fq
file1.2.fq
file1.rem.2.fq
file2.1.fq
file2.rem.1.fq
file2.2.fq
file2.rem.2.fq

for 루프:

list=`for i in *rem*.1.fq; do echo $i | cut -f 1 -d \.; done`
for i in $list; do cat $i.rem.1.fq $i.rem.2.fq > $i.rem.b.fq; done

목록을 작성하지 않고도 이 작업을 수행할 수 있나요? 기능은 무엇입니까 cut -f 1 -d? 파일 이름의 일부가 목록의 두 부분 사이에 있으면 cat $i.rem.1.fq작동하지만 작동하지 않는 이유는 무엇입니까? 이는 이전의 모든 항목(예: file1)을 캡처한다는 의미입니까?cat $i.1.fqrem**rem*

답변1

노력하다:

for i in *.rem.1.fq; do
    cat -- "$i" "${i%.1.fq}.2.fq" > "${i%.1.fq}.b.fq"
done

파일 존재 여부 확인을 추가할 수도 있습니다.

for i in *.rem.1.fq; do
    if [ -e "${i%.1.fq}.2.fq" ] && [ ! -e "${i%.1.fq}.b.fq" ]; then
        cat -- "$i" "${i%.1.fq}.2.fq" > "${i%.1.fq}.b.fq"
    fi
done

질문에서 제안된 접근 방식은 오류가 발생하기 쉽습니다. for파일에 공백이 포함되어 있으면 두 번째 루프가 제대로 작동하지 않을 수 있습니다.

cut -f 1 -d.문자열을 필드(이 경우 로 구분 .)로 분할하고 요청된 필드(이 경우 첫 번째 필드만)를 출력합니다. 문자열이 주어지면 file 1.whatever출력됩니다 file 1. 다시 말하지만, glob 패턴이 – 와일드카드 일치로 파일 이름을 *rem*.1.fq반환할 수 있다는 점을 고려하면 오류가 발생하기 쉽습니다.anyremthing.1.fq*아무것(포함하다아무것도 없다).

더 나은 옵션은 단일 루프를 수행하고 인수 확장을 사용하는 것입니다. 루프 내에서 대체 형식을 사용하여 관련 이름을 가진 다른 파일과 일치시킵니다.

  • 위에서는 glob 패턴이 사용되었습니다 *.rem.1.fq. 더 범위를 좁힐 수도 있습니다. file[0-9].rem.1.fq.
  • ${param%string}루프에서 접미사를 제거하는 데 사용됩니다 .1.fq. 많은 쉘은 다른 형태의 매개변수 확장 대체도 지원합니다. ${param/string/repl}.

"$param"또한 일반적으로 모두 인용 하거나 바꾸는 것이 좋습니다 . 그렇지 않으면 대부분의 쉘이 필드 분할 및 파일 이름 생성을 적용하므로 대신 "$(command)"시도하게 될 수도 있습니다 .cat file 1cat 'file 1'

--파일 이름 이 -.

관련 정보