web-dev-qa-db-fra.com

Curl pour saisir le nom de fichier distant après l'emplacement suivant

Lors du téléchargement d'un fichier à l'aide de curl, comment pourrais-je suivre un emplacement de lien et l'utiliser pour le nom de fichier de sortie (sans connaître à l'avance le nom de fichier distant)?

Par exemple, si l'on clique sur le lien ci-dessous, vous téléchargerez un fichier nommé "pythoncomplete.vim". Cependant, en utilisant les options -O et -L de curl, le nom de fichier est simplement le nom distant d'origine, un "download_script.php? Src_id = 10872" maladroit.

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

Pour télécharger le fichier avec le nom de fichier correct, vous devez connaître le nom du fichier à l'avance:

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

Ce serait excellent si vous pouviez télécharger le fichier sans connaître le nom à l'avance, et sinon, existe-t-il un autre moyen de dérouler rapidement un fichier redirigé via la ligne de commande?

69
Nick S.

Le côté distant envoie le nom de fichier à l'aide de l'en-tête Content-Disposition.

curl 7.21.2 ou plus récent le fait automatiquement si vous spécifiez --remote-header-name/-J.

curl -O -J -L $url
140
jmanning2k

Si vous avez une version récente de curl (7.21.2 ou version ultérieure), voir réponse de @ jmanning2k .

Si vous avez une ancienne version de curl (comme 7.19.7 fournie avec Snow Leopard), faites deux requêtes: un HEAD pour obtenir le nom du fichier depuis l'en-tête de la réponse, puis un 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
31
David J. Liszewski

Si vous pouvez utiliser wget au lieu de curl:

wget --content-disposition $url
11
JacekM

Je voulais commenter la réponse de jmanning2k mais en tant que nouvel utilisateur, je ne peux pas, j'ai donc essayé de modifier son message, ce qui est autorisé mais la modification a été rejetée en disant qu'elle était censée être un commentaire. soupir

Quoi qu'il en soit, voyez cela comme un commentaire à sa réponse merci.

Cela ne semble fonctionner que si l'en-tête ressemble à filename=pythoncomplete.vim comme dans l'exemple, mais certains sites envoient un en-tête qui ressemble à filename*=UTF-8' 'filename.Zip' que l'on n'est pas reconnu par curl 7.28.0

10
Diskutant

Je voulais une solution qui fonctionnait à la fois sur les Mac plus anciens et plus récents, et le code hérité fourni par David pour Snow Leopard ne se comportait pas bien sous Mavericks. Voici une fonction que j'ai créée à partir du code de 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
}

Avec ceci défini, vous pouvez exécuter:

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

Veuillez noter que certains serveurs Web mal configurés serviront le nom en utilisant "Nom de fichier" comme clé, où RFC2183 spécifie qu'il devrait être "nom de fichier". curl ne gère que ce dernier cas.

2
drater

Un exemple utilisant la réponse ci-dessus pour le référentiel d'artefacts Apache Archiva pour extraire la dernière version. La boucle renvoie la ligne Emplacement et le nom de fichier se trouve à la fin de la ligne. Besoin de supprimer le CR à la fin du nom de fichier.

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
1
John Cooper