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

От "человека grep":

три различных программы egrep, fgrep и rgrep доступны. egrep совпадает с grep-E. fgrep, совпадает с grep-F. rgrep, совпадает с grep-r. Прямой вызов или как egrep или как fgrep удерживается от использования, но обеспечивается для разрешения исторических приложений, которые полагаются на них для выполнения неизмененный.

260
05.04.2015, 19:52
14 ответов

Ваш лучший выбор, если в системе GNU:

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

От статистики человека:

Общий размер %s, в байтах

В сценарии удара:

#!/bin/bash
FILENAME=/home/heiko/dummy/packages.txt
FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."

Примечание: см. ответ @chbrown для того, как использовать статистику в терминале на Mac OS X.

254
27.01.2020, 19:27
  • 1
    @haunted85 stat самый простой путь, предполагая, что Вы используете Linux или Cygwin (stat не является стандартным). wc -c как предложено Eugéne является портативным. –  Gilles 'SO- stop being evil' 14.07.2011, 13:02
  • 2
    stat: illegal option -- c –  Iulian Onofrei 27.04.2017, 16:42
  • 3
    stat --printf="%s" file.txt ничего не производит на Debian Jessie... –  woohoo 29.04.2017, 23:36

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

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

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

Править: Это, по-видимому, не столь надежно как stat команда.

8
27.01.2020, 19:27
  • 1
    ссылки я думаю оба ls -l и stat команда дает надежную информацию о размере. Я не нашел ссылки об обратном. ls -s даст размер в количестве блоков. –  dabest1 01.01.2013, 00:23
  • 2
    @dabest1, это не надежно в некотором смысле, что в другом Unix, их вывод может отличаться (и в некотором unixes это). –  Eugene Bujak 02.10.2014, 17:39
  • 3
    Да, IIRC, Солярис не отобразил название группы по умолчанию, ведя к меньшему количеству столбцов в выводе. –  Edward Falk 04.04.2016, 19:31
  • 4
    Так как размер чист числовой, окруженный пробелом, и год даты чист числовой в определенном формате, было бы возможно использовать regexp для обработки user+owner как одного поля, присутствовала ли группа. (осуществление для читателя!) –  MikeW 21.02.2017, 17:31

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

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

5
27.01.2020, 19:27
  • 1
    это или stat -c "%s" ;) –   13.07.2011, 19:29
  • 2
    Эта разновидность du распечатывает размер в блоках 1 024 байтов, не простом количестве байтов. –  Peter Lyons 17.09.2015, 08:10
  • 3
    Отметьте тот стандарт du дайте вывод в количестве 512-байтовых единиц. GNU du кибибайты использования вместо этого, если не названо с POSIXLY_CORRECT в его среде. –  Stéphane Chazelas 08.11.2016, 17:01
  • 4
    Для файлов каталога типа, который дает использование диска каталога, но также и всех других файлов в (рекурсивно). –  Stéphane Chazelas 08.11.2016, 17:02

Вы могли также использовать команду "для подсчета количества слов" (wc):

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

Проблема с wc это, это добавит имя файла и расположит вывод с отступом. Например:

$ wc -c somefile.txt
    1160 somefile.txt

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

wc -c < "$filename"

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

size="$(wc -c <"$filename")"
77
27.01.2020, 19:27
  • 1
    wc -c <"$FILENAME" дает размер без другого хлама, таким образом size=$(wc -c <"$FILENAME"). –  Gilles 'SO- stop being evil' 14.07.2011, 12:58
  • 2
    Просто еще одна точка: Я просто протестировал его и wc -c < file кажется, очень быстр, по крайней мере, на OS X. Я предполагаю, что туалет имеет мозги для попытки к статистике файла, если только-c указан. –  Edward Falk 04.04.2016, 19:29
  • 3
    @EdwardFalk: GNU wc -c использование fstat, но затем ищет на предпоследний блок файла и читает последнее до st_blksize байты. По-видимому, это вызвано тем, что файлы в Linux /proc и /sys например, имейте размеры статистики, которые только приблизительны, и wc хочет сообщить о фактическом размере, не сообщаемом относительно статистики размере. Я предполагаю, что это было бы странно для wc -c сообщить о другом размере, чем wc, но это не идея считать данные из файла, если это - нормальный дисковый файл, и это не находится в памяти. Или хуже, память на ленте почти строки... –  Peter Cordes 12.04.2017, 08:28
  • 4
    Это походит printf все еще видит добавление отступа, например. printf "Size: $size" -> size: <4 spaces> 54339. С другой стороны, echo игнорирует пробел. Какой-либо способ сделать это последовательным? –  Eugene Kulabuhov 02.05.2017, 15:43
file_size_kb=`du -k "$filename" | cut -f1`

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

Солярис, например, поставлется с ударом, но не с stat. Таким образом, это не совсем гипотетически.

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

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

95
27.01.2020, 19:27
  • 1
    du не дает размер файла, он дает признак того, сколько пространства использование файла, который тонко отличается (обычно размер, о котором сообщают du размер файла, окруженного к ближайшему количеству блоков, где блок обычно 512B или 1 КБ или 4 КБ). –  Gilles 'SO- stop being evil' 14.07.2011, 13:00
  • 2
    @Gilles, редкие файлы (т.е. с дырами в них) сообщают о меньше, чем длина. –  vonbrand 10.01.2016, 00:03

Мне нравится опция туалета самому. Соединенный с 'до н.э', можно получить десятичные числа к как много мест как Вам нравится.

Я надеялся улучшать сценарий, у меня было это 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, прежде, чем открыть или перезагрузить изображение в GUI jpeg средство просмотра.

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

BZT

-1
27.01.2020, 19:27
  • 1
    я предпочел бы использовать "статистику" или "ls". Обычно мне не нравится использовать "туалет" для получения размеров файла, потому что он физически читает весь файл. Если у Вас есть много файлов или особенно больших файлов, это может занять много времени. Но Ваше решение интеллектуально... +1. –  Kevin Fegan 09.12.2013, 21:18
  • 2
    , который я согласовываю с понятием использования "статистики" по "туалету" для размера файла, однако если Вы будете использовать "туалет-c", то никакие данные не будут считаны; вместо этого lseek будет использоваться для выяснения числа байтов в файле. lingrok.org/xref/coreutils/src/wc.c#228 –  bbaja42 14.12.2014, 16:38
  • 3
    @bbaja42: отметьте тот Coreutils GNU wc действительно читает последний блок файла, в случае, если stat.st_size было только приближение (как для Linux /proc и /sys файлы). Я предполагаю, что они решили не сделать основной комментарий более сложным, когда они добавили что логическая пара строк вниз: lingrok.org/xref/coreutils/src/wc.c#246 –  Peter Cordes 12.04.2017, 08:53

имеет другой флаг аргумента формата и различные спецификаторы поля. Из Man Stat (1) :

  • -F Формат : отображение информации с использованием указанного формата. См. Раздел «Форматы» для описания действительных форматов.
  • ... Раздел форматов ...
  • Z : Размер файла в байтах.

Так что все вместе сейчас:

stat -f%z myfile1.txt

Примечание. Ответ @ B01's Ответ Для того, как использовать команду STAT на системах GNU / Linux. :)

51
27.01.2020, 19:27

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
27.01.2020, 19:27

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

(
  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/file-size

22
27.01.2020, 19:27

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

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

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

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

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

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

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

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

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

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

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

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

  • IRIX stat (90-е):

     stat -qLs - "$ file" 
     

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

     stat -s - "$ file" 
     

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

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

     стат -L + размер -$ file # st_size файла 
    stat + size - $ file # после разрешения символической ссылки 
     

    или для сохранения в переменной:

     stat -L -A size + size - $ file 
     

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

  • GNU stat (2001); также в BusyBox stat с 2005 г. (скопировано из GNU stat ):

     stat -c% s - "$ file" # st_size файла 
    stat - Lc% s - "$ file" # после разрешения символической ссылки 
     

    (обратите внимание, что значение -L перевернуто по сравнению с IRIX или zsh stat ].

  • BSD stat (2002):

     stat -f% z - "$ file" # st_size файла 
    stat -Lf% z - "$ file "# после разрешения символической ссылки 
     

Или вы можете использовать функцию stat () / lstat () какого-нибудь языка сценариев, например perl :

perl -le 'print((lstat shift)[7])' -- "$file"

AIX также имеет команду istat , которая сбрасывает все stat () (не lstat () , поэтому работать не будет по символическим ссылкам), с которой вы можете постобработать, например:

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

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

В tcsh :

@ size = -Z $file:q

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

Задолго до GNU int создал свою команду stat , то же самое может быть достигнуто с помощью команды GNU find с ее предикатом -printf (уже в 1991 году):

find -- "$file" -prune -printf '%s\n'    # st_size of file
find -L -- "$file" -prune -printf '%s\n' # after symlink resolution

Однако есть одна проблема: это не работает, если $ file начинается с - или является предикатом find (например, ! , ( ...).

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

В соответствии с POSIX вы можете сделать:

LC_ALL=C ls -dn -- "$file" | awk '{print $5; exit}'

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

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

blockdev --getsize64 -- "$device_file"

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

lsblk -bdno size -- "$device_file"

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

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

  • С помощью zsh (после загрузки модуля zsh / system ):

     {sysseek -w end 0 && size = $ ((systell (0)))} <$ file 
     
  • С ksh93 :

     <"$ file" <# ((size = EOF)) 
     

    или

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

     perl -le 'seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN '<"$ file" 
     

Мы видели, что для именованных каналов некоторые системы (по крайней мере, AIX, Solaris, HP / UX) делают объем данных в буфере канала доступным в stat () st_size . Некоторые (например, Linux или FreeBSD) этого не делают.

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

fuser -s -- "$fifo_file" && 
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &FIONREAD, $n) or die$!;
            print unpack "L", $n' <> "$fifo_file"

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

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

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

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

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

  • POSIXLY_CORRECT = 1 ls -sd - "$ file" | awk '{print $ 1; exit} '
  • POSIXLY_CORRECT = 1 du -s - "$ file" (не для каталогов, где это будет включать использование диска файлами внутри).
  • GNU find - "$ file" -printf '% b \ n'
  • zstat -L + block - $ file
  • GNU stat -c% b - "$ file"
  • BSD stat -f% b - - "$ file"
  • perl -le 'print ((lstat shift) [12])' - "$ file"
29
27.01.2020, 19:27

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

Пример

#! /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.

3
27.01.2020, 19:27

Я нашел вкладыш AWK 1, и в нем был баг, но я его исправил. Я также добавил PetaBytes после TeraBytes.

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. Пример; Raspberry Pi не имеет stat , но имеет awk .

3
27.01.2020, 19:27

Самый быстрый и простой (метод ИМО ):

bash_var=$(stat -c %s /path/to/filename)
0
27.01.2020, 19:27

Еще один способ, совместимый с POSIX, заключается в использовании awkс его функцией length(), которая возвращает длину в символах в каждой строке входного файла, исключая символы новой строки. Таким образом, делая

awk '{ sum+=length } END { print sum+NR }' file

мы гарантируем, что NRдобавляется к sum, что приводит к общему количеству символов и общему количеству новых строк, встречающихся в файле. Функция length()в awkпринимает аргумент, который по умолчанию означает length($0)для всей текущей строки.

0
27.01.2020, 19:27

Теги

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