我想创建多个“wget”shell 脚本来使用我们的 HPC 集群下载一批相当大(~3GB)的文件。文件的名称存储在 filenames.txt 中,如下所示:
$cat filenames.txt
file1
file2
file3
...
我想从中获取的网址的结构如下:
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 创建一个 shell 脚本,并将其写入一个名为变量本身的文件中。例如,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
您可以创建一个非常简单的 shell 循环来执行此操作:
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/bash
,在每个文件中,然后wget
您想要的命令(同样将文件名替换为 . )>>
将第二行附加到同一个文件中,而不是覆盖。运行此脚本后:
$ 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"
部分意味着每个 shell 脚本都会写入一个以它下载的文件命名并.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)
,但速度更快一点。