在以下位置后卷曲以获取远程文件名


76

使用curl下载文件时,如何跟踪链接位置并将其用作输出文件名(而无需事先知道远程文件名)?

例如,如果单击下面的链接,则将下载文件名“ pythoncomplete.vim”。但是,使用curl的-O和-L选项,文件名只是原始的远程名称,笨拙的“ download_script.php?src_id = 10872”。

curl -O -L http://www.vim.org/scripts/download_script.php?src_id=10872

为了下载具有正确文件名的文件,您必须事先知道文件名:

curl -o pythoncomplete.vim -L http://www.vim.org/scripts/download_script.php?src_id=10872

如果您可以在不事先知道名称的情况下下载文件,那将是很好的选择;如果不知道,是否还有另一种方法可以通过命令行快速下拉重定向的文件?

Answers:


155

远程端使用Content-Disposition标头发送文件名。

如果您指定--remote-header-name/,curl 7.21.2或更高版本会自动执行此操作-J

curl -O -J -L $url

13
这对我来说不起作用,保存的文件名仍为download_script.php?src_id = 10872格式。我在Macbook Pro上运行curl 7.30.0
ilight,2013年

1
使用curl 7.38.0可以正常工作
ismail

3
无法在OSX上使用curl:curl 7.42.1(x86_64-apple-darwin14.4.0)libcurl / 7.42.1 SecureTransport zlib / 1.2.5 libssh2 / 1.5.0
joelparkerhenderson 2015年

3
作为@Diskutant的“评论中的注释”。在某些常见的情况下,卷曲失败Content-Disposition: attachment; filename = foo.txt=引起它的周围的空格(请参阅:gist.github.com/jnewman/23c993ef50bcd69f9086fcd4e2594928
fncomp

2
如果有人在使用时遇到其他问题,则localhost必须这样做http://localhost或将-J其忽略
mvndaai

34

如果您使用的是最新版本curl(7.21.2或更高版本),请参见@ jmanning2k的答案

我有一个较旧的版本curl(例如Snow Leopard随附的7.19.7),请执行两个请求:aHEAD从响应标头获取文件名,然后a GET

url="http://www.vim.org/scripts/download_script.php?src_id=10872"
filename=$(curl -sI  $url | grep -o -E 'filename=.*$' | sed -e 's/filename=//')
curl -o $filename -L $url

5
谢谢!它在文件名的末尾带有一个问号,因此我tr -d '\r\n'在您的grep和sed命令之间添加了一个,并且效果很好。
尼克·S,

在Cygwin中,我会得到一个名为-L :(文件名我用卷曲--remote头名--remote名URL这似乎工作。
太阳

2
使用curl 7.26.0,可以通过执行“ curl -sI $ url |获得文件名”。grep -oP'(?<=位置:)[^ \ s] +'| xargs基本名称。
aesede

2
第一个curl可能还需要该-L选项。
TNT

2
我不得不使用filename=$(curl -sI $url | grep -o -E 'location:.*$' | sed -e 's/location:=//' | xargs basename)
hoijui


11

我想对jmanning2k的答案发表评论,但作为我的新用户,我无法发表评论,因此我尝试编辑他的允许发布的帖子,但由于说应该是评论而被拒绝。

无论如何,请将此作为对他的答复表示感谢。

这似乎仅在标头看起来像filename=pythoncomplete.vim示例中那样有效,但是某些站点发送的标头看起来像filename*=UTF-8' 'filename.zip'curl 7.28.0无法识别的标头


6

我想要一个适用于旧Mac和新Mac的解决方案,而David为Snow Leopard提供的旧代码在Mavericks下表现不佳。这是我根据David的代码创建的函数:

function getUriFilename() {
    header="$(curl -sI "$1" | tr -d '\r')"

    filename="$(echo "$header" | grep -o -E 'filename=.*$')"
    if [[ -n "$filename" ]]; then
        echo "${filename#filename=}"
        return
    fi

    filename="$(echo "$header" | grep -o -E 'Location:.*$')"
    if [[ -n "$filename" ]]; then
        basename "${filename#Location\:}"
        return
    fi

    return 1
}

使用此定义,您可以运行:

url="http://www.vim.org/scripts/download_script.php?src_id=10872"
filename="$(getUriFilename $url)"
curl -L $url -o "$filename"

2

请注意,某些配置错误的Web服务器将使用“文件名”作为键来提供名称,其中RFC2183指定它应为“文件名”。curl只处理后一种情况。


1

使用上面的答案为Apache Archiva工件存储库提取最新版本的示例。卷曲返回“位置”行,文件名位于该行的末尾。需要删除文件名末尾的CR。

url="http://archiva:8080/restServices/archivaServices/searchService/artifact?g=com.imgur.backup&a=snapshot-s3-util&v=LATEST"
filename=$(curl --silent -sI -u user:password $url | grep Location | awk -F\/ '{print $NF}' | sed 's/\r$//')
curl --silent -o $filename -L -u user:password $url

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.