Як отримати віддалений розмір файлу зі сценарію оболонки?


78

Чи є спосіб отримати розмір віддаленого файлу, наприклад

http://api.twitter.com/1/statuses/public_timeline.json

у сценарії оболонки?


кілька прикладів на цій сторінці, ось один для сценарію оболонки Windows (який може бути подвійним як скрипт bash з невеликими змінами) superuser.com/a/1007898/429721

1
Як щодо wget --spider?
Конрад

Відповіді:


117

Ви можете завантажити файл і отримати його розмір. Але ми можемо зробити краще.

Використовуйте curl, щоб отримати лише заголовок відповіді, використовуючи -Iопцію.

У заголовку відповіді знайдіть, за Content-Length:яким слідуватиме розмір файлу в байтах.

$ URL="http://api.twitter.com/1/statuses/public_timeline.json"
$ curl -sI $URL | grep -i Content-Length
Content-Length: 134

Щоб отримати розмір, використовуйте фільтр, щоб витягти числову частину з вихідних даних:

$ curl -sI $URL | grep -i Content-Length | awk '{print $2}'
134

5
Використовував цю функцію і хотів відправити результат у функцію для форматування байтів у КБ або МБ, і вона має приховане повернення каретки, передає результат, tr -d '\r'щоб видалити їх.
jClark

2
curl -sI $URL | grep -i content-length щоб уникнути регістру, вам слід використовувати -igrep
arulraj.net

Не працює для менеcurl -sI https://code.jquery.com/jquery-3.1.1.min.js | grep -i content-length
fguillen

2
Використовуйте cut -d '' -f2 замість awk. awk більший і повільніший за вирізаний. І щоб бути зрозумілим, це проміжок між окремими лапками. В іншому випадку ця відповідь працює для мене.
В'язень 13

24

Два застереження до інших відповідей:

  1. Деякі сервери не повертають правильну довжину вмісту для запиту HEAD, тому вам може знадобитися виконати повне завантаження.
  2. Швидше за все, ви отримаєте нереально велику відповідь (порівняно із сучасним браузером), якщо не вказати заголовки gzip / deflate.

Крім того, ви можете зробити це без grep / awk або трубопроводів:

curl 'http://api.twitter.com/1/statuses/public_timeline.json' --location --silent --write-out 'size_download=%{size_download}\n' --output /dev/null

І той самий запит зі стисненням:

curl 'http://api.twitter.com/1/statuses/public_timeline.json' --location --silent  -H 'Accept-Encoding: gzip,deflate' --write-out 'size_download=%{size_download}\n' --output /dev/null

Здається, це не працює з переспрямуваннями. Чи не завантажує це також весь файл?
Том Хейл,

1
@TomHale Я думаю, ви можете просто додати -Lдо команди, щоб стежити за переспрямуваннями (у мене немає зручної URL-адреси для перенаправлення для перевірки). Так, він завантажує весь файл.
James H

2
Якщо ви можете залежати від веб - сервера, ви запитуєте , щоб повернути точний Content-Lengthдля HEADзапиту, вам не потрібно завантажувати весь файл. Просто додайте -Iдо прикладу вище, щоб побачити, як він повертає нуль (принаймні, це відбувається 25-25-2019). Моє рішення є більш узагальненим.
James H

9

Подібно до відповіді кодексу , але без заклику grep:

curl -sI http://api.twitter.com/1/statuses/public_timeline.json | awk '/Content-Length/ { print $2 }'

3
Як не дивно, але обраний вами приклад URL-адреси використовує рядки рядків заголовка, content-lengthщо порушує вашу команду. Існує багато способів ігнорувати регістр в awk, але це самий куленепробивний: curl -sI http://api.twitter.com/1/statuses/public_timeline.json | awk '/[Cc]ontent-[Ll]ength/ { print $2 }'... звичайно, grep теж приємний;)
Джоел Меллон,

2
Я думаю, що заголовки змінилися за чотири роки між моєю відповіддю та цим коментарем :)
Johnsyweb

5

Попередні відповіді не спрацюють, якщо є переспрямування. Наприклад, якщо хтось хоче розмір debian iso DVD, він повинен використовувати параметр --location, інакше повідомлений розмір може бути розміром 302 Moved Temporarilyтіла відповіді, а не реального файлу.
Припустимо, у вас є така URL-адреса:

$ url=http://cdimage.debian.org/debian-cd/8.1.0/amd64/iso-dvd/debian-8.1.0-amd64-DVD-1.iso

За допомогою завивки ви можете отримати:

$ curl --head --location ${url}
HTTP/1.0 302 Moved Temporarily
...
Content-Type: text/html; charset=iso-8859-1
...

HTTP/1.0 200 OK
...
Content-Length: 3994091520
...
Content-Type: application/x-iso9660-image
...

Ось чому я віддаю перевагу використанню HEAD, що є псевдонімом lwp-requestкоманди з пакета libwww-perl (на debian). Ще однією його перевагою є те, що він позбавляє зайвих символів \ r , що полегшує подальшу обробку рядків.

Отже, щоб отримати розмір debian iso DVD, можна зробити, наприклад:

$ size=$(HEAD ${url})
$ size=${size##*Content-Length: }
$ size=${size%%[[:space:]]*}

Будь ласка, зверніть увагу, що:

  • цей метод вимагатиме запуску лише одного процесу
  • він буде працювати лише з bash, оскільки використовується спеціальний синтаксис розширення

Для інших оболонок, можливо, доведеться вдатися до sed, awk, grep та ін ..


Приємна відповідь. Чи можна було б це зробити в однокласснику?
кавалькада

size = $ (HEAD $ {url} | grep "Content-Length:" | sed 's /.*: //')
ncarrier

1
На жаль, я не знаю, як редагувати свій попередній коментар, який я розмістив занадто швидко. Однокласне рішення, яке я щойно розмістив, працюватиме, але за рахунок створення 2 додаткових процесів. З іншого боку, він повинен бути сумісним з більшою кількістю снарядів.
ncarrier

5

Я думаю, що найпростіший спосіб зробити це:

  1. використовуйте curl для запуску в беззвучному режимі -s,

  2. тягніть лише заголовки -I(щоб уникнути завантаження цілого файлу)

  3. потім виконайте grep, нечутливий до регістру -i

  4. і поверніть другий аргумент, використовуючи awk $2.

  5. вихід повертається як bytes

Приклади:

curl -sI http://api.twitter.com/1/statuses/public_timeline.json | grep -i content-length | awk '{print $2}'

//output: 52

або

curl -sI https://code.jquery.com/jquery-3.1.1.min.js | grep -i content-length | awk '{print $2}'

//output: 86709

або

curl -sI http://download.thinkbroadband.com/1GB.zip | grep -i content-length | awk '{print $2}'

//output: 1073741824

Показати як кілобайт / мегабайт

Якщо ви хочете показати розмір у кілобайтах, змініть awk на:

awk '{print $2/1024}'

або мегабайт

awk '{print $2/1024/1024}'

3

Прийняте рішення для мене не працювало, це:

curl -s https://code.jquery.com/jquery-3.1.1.min.js | wc -c

1
@fguillen Вам не здається, що краще отримувати дані із заголовків? Оскільки це фактично завантажить файловий буфер в wc.
AO_

@ 0x616f ви маєте рацію, ця інформація також є у заголовках. Чи можете ви запропонувати рішення і помітити мене? Я проголосую за це;)
fguillen

1

У мене є функція оболонки, заснована на відповіді codaddict , яка надає розмір віддаленого файлу в зручному для читання форматі:

remote_file_size () {
  printf "%q" "$*"           |
    xargs curl -sI           |
    grep Content-Length      |
    awk '{print $2}'         |
    tr -d '\040\011\012\015' |
    gnumfmt --to=iec-i --suffix=B # the `g' prefix on `numfmt' is only for systems
  # ^                             # that lack the GNU coreutils by default, i.e.,
  # |                             # non-Linux systems
  # |
  # |                             # in other words, if you're on Linux, remove this
  # |                             # letter `g'; if you're on BSD or Mac, install the GNU coreutils
} # |                                        |
  # +----------------------------------------+

1

Поєднати все вищезазначене для мене працює:

URL="http://cdimage.debian.org/debian-cd/current/i386/iso-dvd/debian-9.5.0-i386-DVD-1.iso"
curl --head --silent --location "$URL" | grep -i "content-length:" | tr -d " \t" | cut -d ':' -f 2

Це поверне лише довжину вмісту в байтах:

3767500800

-1

Я використовую ось так ([Cc]ontent-[Ll]ength:), тому що я отримав сервер, що надає кілька символів довжини вмісту при відповіді заголовка

curl -sI "http://someserver.com/hls/125454.ts" | grep [Cc]ontent-[Ll]ength: | awk '{ print $2 }'

Accept-Ranges: bytes Access-Control-Expose-Headers: Date, Server, Content-Type, Content-Length Server: WowzaStreamingEngine/4.5.0 Cache-Control: no-cache Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: OPTIONS, GET, POST, HEAD Access-Control-Allow-Headers: Content-Type, User-Agent, If-Modified-Since, Cache-Control, Range Date: Tue, 10 Jan 2017 01:56:08 GMT Content-Type: video/MP2T Content-Length: 666460


-1

Це покаже вам детальну інформацію про поточне завантаження

Вам просто потрібно вказати URL-адресу, як показано в прикладі нижче.

$ curl -O -w 'We downloaded %{size_download} bytes\n' 
https://cmake.org/files/v3.8/cmake-3.8.2.tar.gz

вихід

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 7328k  100 7328k    0     0   244k      0  0:00:29  0:00:29 --:--:--  365k
We downloaded 7504706 bytes

Для автоматизованих цілей вам просто потрібно додати команду до файлу сценарію.


-5

інше рішення:

ssh userName@IP ls -s PATH | grep FILENAME | awk '{print$1}'

дає вам розмір у КБ


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