Как я могу получить размер файла в сценарии bash?

Как я могу получить размер файла в сценарии bash?

Как назначить это переменной bash, чтобы впоследствии использовать ее?

181 голос | спросил haunted85 13 J000000Wednesday11 2011, 20:22:32

13 ответов


173

Лучше всего, если в системе GNU:

stat --printf="%s" file.any

ПРИМЕЧАНИЕ: см. @chbrown ниже ответ, как использовать stat в терминале в Mac OS X или

#!/bin/bash
FILENAME=/home/heiko/dummy/packages.txt
FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."
ответил b01 13 J000000Wednesday11 2011, 20:29:27
71
file_size_kb=`du -k "$filename" | cut -f1`

Проблема с использованием stat заключается в том, что это расширение GNU (Linux). du -k и cut -f1 задаются POSIX и поэтому переносятся в любую систему Unix.

Solaris, например, поставляется с bash, но не с stat. Так что это не совсем гипотетически.

ls имеет аналогичную проблему, так как точный формат вывода не указан, поэтому синтаксический анализ его вывода не может выполняться портативно. du -h также является расширением GNU.

Придерживайтесь переносных конструкций, где это возможно, и вы сделаете чью-то жизнь проще в будущем. Возможно, ваш собственный.

ответил Nemo 13 J000000Wednesday11 2011, 20:34:23
56

Вы также можете использовать команду «count count» (wc):

wc -c "$filename" | awk '{print $1}'

Проблема с wc заключается в том, что она добавит имя файла и сделает отступ выходным. Например:

$ wc -c somefile.txt
    1160 somefile.txt

Если вы хотите избежать связывания полного интерпретируемого языка или редактора потока только для получения количества файлов, просто перенаправьте входные данные из файла, чтобы wc никогда не видел имя файла:

wc -c < "$filename"

Эта последняя форма может использоваться с подстановкой команд, чтобы легко получить значение, которое вы искали в качестве переменной оболочки, как указано Жиль ниже.

size="$(wc -c <"$filename")"
ответил Eugéne 14 J000000Thursday11 2011, 12:47:04
34

BSD (Mac OS X) stat имеет другой флаг аргументов формата и разные спецификаторы полей. Из man stat(1):

  • -f format: отображение информации в указанном формате. См. Раздел FORMATS для описания допустимых форматов.
  • ... раздел FORMATS ...
  • z: размер файла в байтах.

Итак, теперь все вместе:

stat -f%z myfile1.txt
ответил chbrown 16 FebruaryEurope/MoscowbMon, 16 Feb 2015 03:23:08 +0300000000amMon, 16 Feb 2015 03:23:08 +030015 2015, 03:23:08
20

Этот сценарий сочетает в себе множество способов расчета размера файла:

(
  du --apparent-size --block-size=1 "$file" 2>/dev/null ||
  gdu --apparent-size --block-size=1 "$file" 2>/dev/null ||
  find "$file" -printf "%s" 2>/dev/null ||
  gfind "$file" -printf "%s" 2>/dev/null ||
  stat --printf="%s" "$file" 2>/dev/null ||
  stat -f%z "$file" 2>/dev/null ||
  wc -c <"$file" 2>/dev/null
) | awk '{print $1}'

Скрипт работает во многих Unix-системах, включая Linux, BSD, OSX, Solaris, SunOS и т. д.

Размер файла показывает количество байтов. Это видимый размер, который представляет собой байты, которые файл использует на типичном диске, без специального сжатия или специальных разреженных областей или нераспределенных блоков и т. Д.

Этот сценарий имеет производственную версию с большей помощью и дополнительными опциями здесь: https://github.com/SixArm/sixarm_unix_shell_scripts/blob/master/file-size

ответил joelparkerhenderson 17 J000000Friday15 2015, 06:07:21
18

Зависит от того, что вы подразумеваете под size .

size=$(wc -c < "$file")

предоставит вам количество байтов, которые можно прочитать из файла. IOW, это размер содержимого файла. Однако он прочитает содержимое файла (за исключением того, что файл является обычным файлом или символической ссылкой на обычный файл в большинстве реализаций wc в качестве оптимизации). Это может иметь побочные эффекты. Например, для именованного канала то, что было прочитано, больше не может быть прочитано снова и для таких вещей, как /dev/zero или /dev/random, которые имеют бесконечный размер , это займет некоторое время. Это также означает, что вам нужен read доступ к файлу.

Это стандартная и портативная, однако обратите внимание, что некоторые реализации wc могут включать в себя ведущие пробелы в этом выпуске. Один из способов избавиться от них - использовать:

size=$(($(wc -c < "$file")))

или во избежание ошибки о пустом арифметическом выражении в dash или yash, когда wc не выводит результат (например, когда файл может " t будет открыт):

size=$(($(wc -c < "$file") +0))

ksh93 имеет встроенный wc (при включении его вы также можете вызвать его как команду command /opt/ast/bin/wc) что делает его наиболее эффективным для обычных файлов в этой оболочке.

В разных системах есть команда под названием stat, которая является интерфейсом к системным вызовам stat() или lstat().

Данные отчета, найденные в inode. Одна из этих данных - это атрибут st_size. Для обычных файлов это размер содержимого (сколько данных можно было прочитать из него при отсутствии ошибки (это то, что используют большинство wc -c) в своей оптимизации)). Для символических ссылок это размер в байтах целевого пути. Для именованных каналов, в зависимости от системы, это либо 0, либо количество байтов, находящихся в настоящее время в буфере канала. То же самое для блочных устройств, где в зависимости от системы вы получаете 0 или размер в байтах базового хранилища.

Вам не нужно разрешение на чтение файла для получения этой информации, только разрешение на поиск в каталоге, к которому он привязан.

По хронологическому порядку:

  • IRIX stat (90-е ):

    stat -qLs -- "$file"
    

    возвращает st_size атрибут $file (lstat()) или:

    stat -s -- "$file"
    

    то же самое, за исключением случаев, когда $file является символической ссылкой, и в этом случае это символ st_size файла после разрешения символической ссылки.

  • zsh stat builtin (теперь также известный как stat) в модуле zstat (загружается с помощью zsh/stat) (1997):

    zmodload zsh/stat

    или сохранить в переменной:

    stat -L +size -- $file # st_size of file
    stat +size -- $file    # after symlink resolution
    

    , очевидно, это наиболее эффективно в этой оболочке.

  • GNU stat -L -A size +size -- $file (2001); также в BusyBox stat с 2005 года (скопировано из GNU stat):

    stat

    (обратите внимание, что значение stat -c %s -- "$file" # st_size of file stat -Lc %s -- "$file" # after symlink resolution отменено по сравнению с IRIX или -L zsh.

  • BSDs stat (2002):

    stat

Или вы можете использовать функцию stat -f %z -- "$file" # st_size of file stat -Lf %z -- "$file" # after symlink resolution /stat() для некоторого языка сценариев, например lstat():

perl

AIX также имеет perl -le 'print((lstat shift)[7])' -- "$file" , который выведет все istat (не stat(), поэтому не будет работать с символическими ссылками), и что вы может выполнять пост-обработку, например:

lstat()

(спасибо @JeffSchaller за помощь в детализации ).

В LC_ALL=C istat "$file" | awk 'NR == 4 {print $5}' :

tcsh

(размер после разрешения символической ссылки)

Задолго до того, как GNU представила свой @ size = -Z $file:q команды, то же самое можно было бы сделать с помощью команды GNU stat с ее предикатом find (уже в 1991 году):

-printf

Одна проблема заключается в том, что это не работает, если find -- "$file" -prune -printf '%s\n' # st_size of file find -L -- "$file" -prune -printf '%s\n' # after symlink resolution начинается с $file или является предикатом - (например, find, ! ...).

Стандартная команда для получения информации ( /stat(): lstat().

POSIXly, вы можете сделать:

ls

и добавьте LC_ALL=C ls -dn -- "$file" | awk '{print $5; exit}' для него после разрешения symlink. Это не работает для файлов устройств, хотя поле 5 th является основным номером устройства, а не размером.

Для блочных устройств, систем, где -L возвращает 0 для stat(), обычно имеют другие API-интерфейсы, чтобы сообщать размер блочного устройства. Например, Linux имеет st_size BLKGETSIZE64, и большинство дистрибутивов Linux теперь поставляются с командой ioctl(), которая может ее использовать:

blockdev

Однако для этого вам требуется разрешение на чтение файла устройства. Обычно можно получить размер другими способами. Например (еще в Linux):

blockdev --getsize64 -- "$device_file"

Должна работать, кроме пустых устройств.

Подход, который работает для всех файлов с возможностью поиска (включая обычные файлы, большинство блочных устройств и некоторые символьные устройства), заключается в том, чтобы открыть файл и найти его до конца:

  • С помощью lsblk -bdno size -- "$device_file" (после загрузки модуля zsh):

    zsh/system
  • С помощью {sysseek -w end 0 && size=$((systell(0)))} < $file :

    ksh93

    или

    < "$file" <#((size=EOF))
    
  • с { size=$(<#((EOF))); } < "$file" :

    perl

Для именованных каналов мы видели, что некоторые системы (AIX, Solaris, HP /UX, по крайней мере) делают объем данных в буфере каналов доступным в perl -le 'seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN' < "$file" 'stat(). Некоторые (например, Linux или FreeBSD) этого не делают.

В Linux, по крайней мере, вы можете использовать st_size FIONREAD после открытия канала (в режиме чтения + записи, чтобы избежать его зависания):

ioctl()

Однако обратите внимание, что, хотя он не читает содержимое канала, простое открытие именованного канала здесь может по-прежнему иметь побочные эффекты. Мы используем fuser -s -- "$fifo_file" && perl -le 'require "sys/ioctl.ph"; ioctl(STDIN, &FIONREAD, $n) or die$!; print unpack "L", $n' <> "$fifo_file" , чтобы сначала проверить, что в каком-то процессе уже открыт канал, чтобы облегчить это, но это не является надежным, поскольку fuser, возможно, не сможет проверить все процессы.

Теперь мы рассматриваем только размер первичных данных, связанных с файлами. Это не учитывает размер метаданных и всю вспомогательную инфраструктуру, необходимую для хранения этого файла.

Другой атрибут inode, возвращаемый fuser, это stat(). Это число блоков по 512 байт, которые используются для хранения данных файла (а иногда и некоторых его метаданных, таких как расширенные атрибуты файловых систем ext4 в Linux). Это не включает сам индекс или записи в каталогах, к которым связан файл.

Размер и использование диска не обязательно тесно связаны с сжатием, редкостью (иногда некоторыми метаданными), дополнительная инфраструктура, такая как косвенные блоки в некоторых файловых системах, влияет на последних.

Обычно для использования дискового пространства используется st_blocks. Большинство команд, перечисленных выше, смогут получить эту информацию.

  • du
  • POSIXLY_CORRECT=1 ls -sd -- "$file" | awk '{print $1; exit}' (не для каталогов, где это будет включать использование файлов в файлах внутри).
  • GNU POSIXLY_CORRECT=1 du -s -- "$file"
  • find -- "$file" -printf '%b\n'
  • GNU zstat -L +block -- $file
  • BSD stat -c %b -- "$file"
  • stat -f %b -- "$file"
ответил Stéphane Chazelas 7 12016vEurope/Moscow11bEurope/MoscowMon, 07 Nov 2016 00:27:09 +0300 2016, 00:27:09
7

ls -l filename предоставит вам много информации о файле, включая его размер файла, разрешения и владельца.

Размер файла в пятом столбце и отображается в байтах. В приведенном ниже примере размер файла составляет менее 2 КБ:

-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php

Изменить: Это, по-видимому, не так надежно, как команда stat.

ответил Druckles 13 J000000Wednesday11 2011, 20:24:19
5

stat , похоже, делает это с наименьшими системными вызовами:

$ set debian-live-8.2.0-amd64-xfce-desktop.iso

$ strace stat --format %s $1 | wc
    282    2795   27364

$ strace wc --bytes $1 | wc
    307    3063   29091

$ strace du --bytes $1 | wc
    437    4376   41955

$ strace find $1 -printf %s | wc
    604    6061   64793
ответил 9 Jpm1000000pmSat, 09 Jan 2016 23:27:45 +030016 2016, 23:27:45
3

du filename расскажет вам об использовании диска в байтах.

Я предпочитаю du -h filename, который дает вам размер в человекообразном формате.

ответил Teddy 13 J000000Wednesday11 2011, 20:25:34
2

Привет всем,

Я обнаружил, что кто-то сделал линейку AWK 1, и у нее была ошибка, но я ее исправил. Я также добавил в PetaBytes после TerraBytes.

FILE_SIZE= 234234 # FILESIZE IN BYTES
FILE_SIZE=$(echo "${FILE_SIZE}" | awk '{ split( "B KB MB GB TB PB" , v ); s=1; while( $1>1024 ){ $1/=1024; s++ } printf "%.2f %s", $1, v[s] }')

Учитывая, что stat не входит в каждую систему, я бы использовал решение AWK. Пример; у малины Pi нет stat , но у него есть awk .

Наслаждайтесь ~!

ответил findrbot_admin 3 J000000Monday17 2017, 03:21:31
1

Создайте небольшие служебные функции в сценариях оболочки, на которые вы можете делегировать.

Пример

#! /bin/sh -
# vim: set ft=sh

# size utility that works on GNU and BSD systems
size(){
    case $(uname) in
        (Darwin | *BSD*)
            stat -Lf %z -- "$1";;
        (*) stat -c %s -- "$1"
    esac
}

for f do
    printf '%s\n' "$f : $(gzip < "$f" | wc -c) bytes (versus $(size "$f") bytes)"
done

Основываясь на информации из ответа @ Stà © phane Chazelas.

ответил oligofren 11 Jpm1000000pmWed, 11 Jan 2017 16:00:37 +030017 2017, 16:00:37
0

Мне нравится сам wc. Сопряженный с помощью «bc», вы можете получить десятичные знаки на столько мест, сколько пожелаете.

Я искал улучшения скрипта, который у меня был, что awk'ed из столбца «размер файла» команды «ls -alh». Я не хотел иметь размер только целочисленных файлов, и два десятичных знака, казалось, соответствовали, поэтому, прочитав эту дискуссию, я придумал код ниже.

Я предлагаю разбить строку в точках с запятой, если вы включили это в скрипт.

file=$1; string=$(wc -c $file); bite=${string% *}; okay=$(echo "scale=2; $bite/1024" | bc);friend=$(echo -e "$file $okay" "kb"); echo -e "$friend"

Мой скрипт называется gpfl , для «получения длины файла изображения». Я использую его после выполнения mogrify в файле в imagemagick перед открытием или повторной загрузкой изображения в средстве просмотра JPEG-файлов.

Я не знаю, как это оценивается как «ответ», поскольку он сильно заимствует из того, что уже было предложено и обсуждено. Поэтому я оставлю это там.

BZT

ответил BZT 12 PMpFri, 12 Apr 2013 22:16:13 +040016Friday 2013, 22:16:13
0

Это можно сделать с помощью команды du. Вот рабочий пример: Это программное обеспечение предлагает вам способ выбора файла, в котором вы хотите узнать его файл. (также отправьте git )

#!/bin/bash
# File size

FILE_SIZE=$"du -h"
# Clear the terminal
tput clear

# Request the user where and which file with an example
printf "Which file do you wish to calculate?\n"
printf "Please provide its place and name like /home/user/file-size.sh\n"
read FILE

# Calculate with du -h (human readable) and print the output
$FILE_SIZE $FILE
ответил aurelien 6 72016vEurope/Moscow11bEurope/MoscowSun, 06 Nov 2016 19:28:42 +0300 2016, 19:28:42

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132