Curl, um den entfernten Dateinamen nach dem folgenden Ort abzurufen


74

Wie würde ich beim Herunterladen einer Datei mit curl einem Link-Speicherort folgen und diesen für den Ausgabedateinamen verwenden (ohne den Remote-Dateinamen im Voraus zu kennen)?

Wenn Sie beispielsweise auf den folgenden Link klicken, laden Sie einen Dateinamen mit dem Namen "pythoncomplete.vim" herunter. Bei Verwendung der Optionen -O und -L von curl ist der Dateiname jedoch einfach der ursprüngliche Remote-Name, ein ungeschicktes "download_script.php? Src_id = 10872".

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

Um die Datei mit dem richtigen Dateinamen herunterzuladen, müssen Sie den Namen der Datei im Voraus kennen:

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

Es wäre hervorragend, wenn Sie die Datei herunterladen könnten, ohne den Namen im Voraus zu kennen. Wenn nicht, gibt es eine andere Möglichkeit, eine umgeleitete Datei schnell über die Befehlszeile abzurufen?

Antworten:


154

Die Remote-Seite sendet den Dateinamen über den Content-Disposition-Header.

curl 7.21.2 oder neuer führt dies automatisch aus, wenn Sie --remote-header-name/ angeben -J.

curl -O -J -L $url

13
Dies funktioniert bei mir nicht, der gespeicherte Dateiname liegt immer noch im Format download_script.php? Src_id = 10872 vor. Ich verwende Curl 7.30.0 auf meinem MacBook Pro
ilight

3
Unter OSX funktioniert Curl nicht: Curl 7.42.1 (x86_64-apple-darwin14.4.0) libcurl / 7.42.1 SecureTransport zlib / 1.2.5 libssh2 / 1.5.0
joelparkerhenderson

1
Funktioniert nicht unter OSX El Capitan: Curl 7.43.0 (x86_64-apple-darwin15.0) libcurl / 7.43.0 SecureTransport zlib / 1.2.5
jgp

3
Als @Diskutant "Kommentare in einer Antwort" unten. Dies scheitert im etwas häufigen Fall von Curl Content-Disposition: attachment; filename = foo.txt. Die Leerzeichen um die =Ursache herum (siehe: gist.github.com/jnewman/23c993ef50bcd69f9086fcd4e2594928 )
fncomp

2
Falls jemand anderes darauf stößt, wenn Sie es verwenden localhost, müssen Sie es machen http://localhostoder das -Jwird ignoriert
mvndaai

34

Wenn Sie eine aktuelle Version von curl(7.21.2 oder höher) haben, lesen Sie die Antwort von @ jmanning2k .

curlWenn Sie eine ältere Version von (wie 7.19.7, die mit Snow Leopard geliefert wurde) haben, führen Sie zwei Anfragen aus: a HEAD, um den Dateinamen aus dem Antwortheader abzurufen , dann 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
Vielen Dank! Es kam mit einem Fragezeichen am Ende des Dateinamens zurück, also habe ich ein tr -d '\r\n'zwischen Ihren Befehlen grep und sed hinzugefügt , und es hat wunderbar funktioniert.
Nick S.

In Cygwin erhalte ich einen Dateinamen namens -L :(. Ich habe die URL curl --remote-header-name --remote-name verwendet, die zu funktionieren schien.
So

2
Mit Curl 7.26.0 konnte ich den Dateinamen erhalten, indem ich ´curl -sI $ url | machte grep -oP '(? <= Ort :) [^ \ s] +' | xargs basename´.
Aesede

2
Der erste curlwürde wahrscheinlich auch die -LOption brauchen .
TNT

2
Ich musste verwendenfilename=$(curl -sI $url | grep -o -E 'location:.*$' | sed -e 's/location:=//' | xargs basename)
hoijui


11

Ich wollte die Antwort von jmanning2k kommentieren, aber als neuer Benutzer kann ich das nicht. Deshalb habe ich versucht, seinen Beitrag zu bearbeiten, was zulässig ist, aber die Bearbeitung wurde abgelehnt, da es sich um einen Kommentar handeln sollte. Seufzer

Wie auch immer, sehen Sie dies als Kommentar zu seiner Antwort, danke.

Dies scheint nur zu funktionieren, wenn der Header wie filename=pythoncomplete.vimim Beispiel aussieht , aber einige Sites senden einen Header, der so aussieht, filename*=UTF-8' 'filename.zip'dass er von Curl 7.28.0 nicht erkannt wird


6

Ich wollte eine Lösung, die sowohl auf älteren als auch auf neueren Macs funktioniert, und der Legacy-Code, den David für Snow Leopard bereitstellte, verhielt sich unter Mavericks nicht gut. Hier ist eine Funktion, die ich basierend auf Davids Code erstellt habe:

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
}

Mit dieser Definition können Sie Folgendes ausführen:

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

2

Bitte beachten Sie, dass bestimmte falsch konfigurierte Webserver den Namen mit "Dateiname" als Schlüssel verwenden, wobei RFC2183 angibt, dass er "Dateiname" sein soll. Curl behandelt nur den letzteren Fall.


1

Ein Beispiel mit der obigen Antwort für das Apache Archiva-Artefakt-Repository zum Abrufen der neuesten Version. Die Locke gibt die Position Zeile zurück und der Dateiname befindet sich am Ende der Zeile. Die CR muss am Ende des Dateinamens entfernt werden.

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

0

Ich hatte das gleiche Problem wie John Cooper. Ich habe keinen Dateinamen, sondern einen Standortdateinamen zurückbekommen. Seine Antwort hat auch funktioniert, aber es gibt 2 Befehle. Dieser Oneliner hat bei mir funktioniert ....

url="https://download.mozilla.org/?product=firefox-latest-ssl&os=linux64&lang=de";url=$(curl -L --head -w '%{url_effective}' $url 2>/dev/null | tail -n1) ; curl -O $url

Gestohlen und einige Sachen von /unix/126252/resolve-filename-from-a-remote-url-without-downloading-a-file hinzugefügt

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.