Згорніть, щоб захопити віддалене ім'я файлу після наступного розташування


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

Було б чудово, якби ви змогли завантажити файл, не знаючи його заздалегідь, і якщо ні, чи є інший спосіб швидко витягнути перенаправлений файл через командний рядок?

Відповіді:


155

Віддалена сторона надсилає ім'я файлу за допомогою заголовка Content-Disposition.

curl 7.21.2 або новіша робить це автоматично, якщо вказати --remote-header-name/ -J.

curl -O -J -L $url

13
Це не працює для мене, назва збереженого файлу все ще у форматі download_script.php? Src_id = 10872. Я біжу завиток 7.30.0 на моєму Macbook Pro
ilight

1
Працюйте добре з curl 7.38.0
ismail

3
Не працює з curl на OSX: curl 7.42.1 (x86_64-apple-darwin14.4.0) libcurl / 7.42.1 SecureTransport zlib / 1.2.5 libssh2 / 1.5.0
joelparkerhenderson

3
Як @Diskutant "коментує відповідь" нижче. Це не вдається завити в дещо поширеному випадку Content-Disposition: attachment; filename = foo.txt. Простори навколо цього =спричиняють (див .: gist.github.com/jnewman/23c993ef50bcd69f9086fcd4e2594928 )
fncomp

2
Якщо хтось інший localhosthttp://localhost-J
зіткнеться

34

Якщо у вас остання версія curl(7.21.2 або пізнішої версії), див. Відповідь @ jmanning2k .

Якщо у вас є старіша версія curl(наприклад, 7.19.7, яка постачається із Snow Leopard), зробіть два запити: a, HEADщоб отримати ім’я файлу з заголовка відповіді, а потім 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, і це чудово працювало.
Nick S.

У cygwin я отримую ім'я файлу під назвою -L :(. Я використовував curl --remote-header-name --remote-name URL, який, здавалося, працював.
Нд,

2
З curl 7.26.0 я міг отримати ім'я файлу, виконавши ´curl -sI $ url | grep -oP '(? <= Розташування:) [^ \ s] +' | xargs basename´.
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, і застарілий код, який Девід надав для Snow Leopard, погано поводився під Mavericks. Ось функція, яку я створив на основі коду Девіда:

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

Зверніть увагу, що деякі неправильно налаштовані веб-сервери будуть подавати назву, використовуючи "Ім'я файлу" як ключ, де RFC2183 вказує, що це має бути "ім'я файлу". curl обробляє лише останній випадок.


1

Приклад використання відповіді вище для сховища артефактів Apache Archiva для випуску останньої версії. Завиток повертає рядок Location, а ім'я файлу знаходиться в кінці рядка. Потрібно видалити 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

0

У мене була та сама проблема, як у Джона Купера. Я не отримав назви файлу, крім назви файлу місцезнаходження. Його відповідь також спрацювала, але це 2 команди. Цей лайнер працював у мене ....

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

Викрадено та додано деякі речі з /unix/126252/resolve-filename-from-a-remote-url-without-downloading-a-file

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.