변수 목록에서 변수로 명명된 파일을 추가하고 작성합니다.

변수 목록에서 변수로 명명된 파일을 추가하고 작성합니다.

HPC 클러스터를 사용하여 상당히 큰(~3GB) 파일 배치를 다운로드하기 위해 여러 개의 "wget" 셸 스크립트를 생성하고 싶습니다. 파일 이름은 다음과 같이 filenames.txt에 저장됩니다.

$cat filenames.txt
file1
file2
file3
...

내가 얻으려는 URL은 다음과 같이 구성됩니다.

ftp://host.com/dir1/dir2/file1/file1.sra
ftp://host.com/dir1/dir2/file2/file2.sra
ftp://host.com/dir1/dir2/file3/file3.sra

각 wget에 대한 쉘 스크립트를 생성하고 이를 변수 자체라는 파일에 쓰고 싶습니다. 예를 들어 file1.sh에는 다음이 포함되어야 합니다.

#!/bin/bash
wget ftp://host.com/dir1/dir2/file1/file1.sra

그리고 file2.sh에는 다음이 포함되어야 합니다.

#!/bin/bash
wget ftp://host.com/dir1/dir2/file2/file2.sra

보시다시피 일치하는 패턴은 1) URL과 2) 작성할 파일 이름입니다. 파일 이름에 URL을 "추가"한 다음 그 이름을 딴 .sh 파일에 쓰려면 어떻게 해야 합니까?

답변1

이를 수행하기 위해 매우 간단한 쉘 루프를 만들 수 있습니다.

while read filename
do
    echo '#!/bin/bash' > $filename.sh
    echo "wget ftp://host.com/dir1/dir2/$filename/$filename.sra" >> $filename.sh
done < filenames.txt

이는 각 줄을 읽고 filenames.txt호출 한 다음, 각 줄에 대해 대체된 파일의 줄로 이름 이 지정된 filename파일을 작성합니다 . 파일에는 두 줄이 있습니다: 각 파일에 , 원하는 명령(다시 파일 이름을 . 로 대체) 은 덮어쓰는 대신 동일한 파일에 두 번째 줄을 추가합니다. 이 스크립트를 실행한 후:$filename.sh$filename#!/bin/bashwget>>

$ cat file1.sh 
#!/bin/bash
wget ftp://host.com/dir1/dir2/file1/file1.sra
$ cat file2.sh
#!/bin/bash
wget ftp://host.com/dir1/dir2/file2/file2.sra

루프 본문 내부에 세 번째 줄을 추가할 수 있습니다.

chmod a+x "$filename.sh"

이후에 스크립트를 실행 가능하게 만듭니다. 행 바로 위에 놓습니다 done.


파일 이름에 공백이나 기타 특수 문자가 포함되어 있으면 여러 수준에서 문제가 발생하지만 영숫자 이름의 경우에는 잘 작동합니다.

답변2

다음 명령을 사용하십시오.

awk -v url='ftp://host.com/dir1/dir2' '{printf "#!/bin/bash\nwget %s/%s/%s.sra\n",url,$1,$1 >$1".sh"}' filenames.txt

이 명령을 실행하면 아래와 같이 일련의 파일이 현재 디렉터리에 나타납니다.

$ ls *.sh
file1.sh  file2.sh  file3.sh

각 콘텐츠의 내용은 다음과 유사합니다.

$ cat file1.sh
#!/bin/bash
wget ftp://host.com/dir1/dir2/file1/file1.sra

어떻게 작동하나요?

  • -v url='ftp://host.com/dir1/dir2'

    이는 a를 변수 url로 정의합니다.awk

  • printf "#!/bin/bash\nwget %s/%s/%s.sra\n",url,$1,$1 >$1".sh"

    그러면 필요한 모든 파일이 인쇄됩니다. 이 >$1".sh"부분은 각 쉘 스크립트가 다운로드한 파일 이름을 따서 파일 이름을 작성하고 .sh확장자를 추가한다는 것을 의미합니다.

답변3

for루프 printf와 명령 대체를 사용하는 제안도 있습니다 $().

for file in $(<filenames); do
    printf "%s\n%s\n" '#!/bin/bash' "wget ftp://host.com/dir1/dir2/${file}/${file}.sra" > "${file}.sh"
done

유일하게 중요한 부분은 아마도 $(<filename)동일 $(cat filename)하지만 조금 더 빠르다는 것입니다.

관련 정보