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

<p>как я могу получить размер файла в bash-скрипте?</p><p>как мне присвоить это переменной bash, чтобы я мог использовать ее позже?</p>

<p>ваш лучший выбор, если в системе gnu:</p><pre><code>stat --printf="%s" file.any </code></pre><p>от <a href="https://linux.die.net/man/1/stat">стат</a> :</p><blockquote> <p>% s общий размер, в байтах</p> </blockquote><p>в скрипте bash:</p><pre><code>#!/bin/bash filename=/home/heiko/dummy/packages.txt filesize=$(stat -c%s "$filename") echo "size of $filename = $filesize bytes." </code></pre><p>примечание: см. <a href="https://unix.stackexchange.com/a/185039/9071">ответ @ chbrown</a> как использовать stat в терминале в mac os x.</p>

<pre><code>file\_size\_kb=`du -k "$filename" | cut -f1 проблема с использованием stat заключается в том, что это расширение gnu (linux)). <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/du.html">du -k и <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cut.html">cut -f1 определены posix и поэтому переносимы на любую систему unix.например, solaris поставляется с bash, но не с stat. так что это не совсем гипотетически.ls имеет аналогичную проблему в том, что точный формат вывода не указан, поэтому анализ его вывода не может быть выполнен переносимым. du -h также является расширением gnu.придерживайтесь переносных конструкций, где это возможно, и в будущем вы сделаете чью-то жизнь проще. может быть, ваш собственный.

вы также можете использовать команду "количество слов" (wc):wc -c "$filename" | awk '{print $1}' проблема с wc заключается в том, что он добавит имя файла и сделает отступ. например:$ wc -c somefile.txt 1160 somefile.txt </code></pre><p>если вы хотите избежать создания цепочки полностью интерпретируемого языка или редактора потоков только для того, чтобы получить счетчик размера файла, просто перенаправьте ввод из файла, чтобы <code>wc</code> никогда не видел имя файла:</p><pre><code>wc -c < "$filename" эта последняя форма может использоваться с подстановкой команд, чтобы легко получить значение, которое вы искали как переменную оболочки, как указано в <a href="https://unix.stackexchange.com/users/885/gilles">gilles ниже.size="$(wc -c <"$filename")" 

bsd (macos) stat имеет другой флаг аргумента формата и другие спецификаторы полей. от man stat(1): -f format: отображение информации в указанном формате. смотрите раздел formats для описания допустимых форматов. ... раздел форматы ... z: размер файла в байтах. итак, все вместе сейчас:stat -f%z myfile1.txt примечание. см. <a href="https://unix.stackexchange.com/a/16644/50950">ответ @ b01 , чтобы узнать, как использовать команду stat в системах gnu/linux. :)

зависит от того, что вы подразумеваете под  размером .size=$(wc -c < "$file") даст вам количество байтов, которые можно прочитать из файла. iow, это размер содержимого файла. однако он будет читать содержимое файла (за исключением случаев, когда файл является обычным файлом или символической ссылкой на обычный файл в большинстве реализаций wc в качестве оптимизации). это может иметь побочные эффекты. например, для именованного канала прочитанное больше не может быть прочитано снова, а для таких вещей, как /dev/zero или /dev/random, которые имеют бесконечный размер, потребуется некоторое время. это также означает, что вам нужно read разрешение на файл, и  отметка времени последнего доступа  файла может быть обновлена.это стандартно и переносимо, однако обратите внимание, что некоторые реализации wc могут включать начальные пробелы в этом выводе. один из способов избавиться от них - использовать:size=$(($(wc -c < "$file"))) </code></pre><p>или чтобы избежать ошибки о пустом арифметическом выражении в <code>dash</code> или <code>yash</code>, когда <code>wc</code> не выдает выходных данных (например, когда файл не может быть открыт):</p><pre><code>size=$(($(wc -c < "$file") +0)) ksh93 имеет встроенный wc (при условии, что вы включите его, вы также можете вызвать его как command /opt/ast/bin/wc), что делает его наиболее эффективным для обычных файлов в этой оболочке.различные системы имеют команду stat, которая является интерфейсом системных вызовов stat() или lstat().те сообщают информацию, найденную в inode. одной из этих сведений является атрибут st_size. для обычных файлов это размер содержимого (сколько данных можно прочитать из него при отсутствии ошибок (именно это большинство реализаций wc -c используют при оптимизации)). для символических ссылок это размер в байтах целевого пути. для именованных каналов, в зависимости от системы, это либо 0, либо количество байтов, находящихся в данный момент в буфере канала. то же самое для блочных устройств, где в зависимости от системы вы получаете 0 или размер в байтах базового хранилища.вам не нужно разрешение на чтение файла, чтобы получить эту информацию, только разрешение на поиск в каталоге, с которым он связан.по хронологическому порядку есть:   <a href="http://nixdoc.net/man-pages/irix/stat.1.html">irix stat (90-е): stat -qls -- "$file" </code></pre> <p>возвращает атрибут <code>st\_size</code> <code>$file (lstat()) или: stat -s -- "$file" </code></pre> <p>то же самое, за исключением случаев, когда <code>$file является символической ссылкой, в этом случае это st_size файла после разрешения символической ссылки.    <a href="http://zsh.sourceforge.net/doc/release/zsh-modules.html#the-zsh_002fstat-module">zsh stat встроенный (теперь также известный как zstat) в модуле zsh/stat (загружен с zmodload zsh/stat) (1997): stat -l +size -- $file # st\_size of file stat +size -- $file # after symlink resolution  или хранить в переменной: stat -l -a size +size -- $file </code></pre> <p>очевидно, это самый эффективный в этой оболочке.</p> </li> <li> <p> <a href="https://www.gnu.org/software/coreutils/manual/html\_node/stat-invocation.html">gnu <code>stat</code></a> (2001); также в busybox <code>stat</code> с 2005 года (скопировано из gnu <code>stat</code>):</p> <pre><code>stat -c %s -- "$file" # st_size of file stat -lc %s -- "$file" # after symlink resolution </code></pre> <p>(обратите внимание, что значение <code>-l</code> обратное по сравнению с irix или <code>zsh</code> <code>stat</code>.</p> </li> <li> <p> <a href="https://www.freebsd.org/cgi/man.cgi?query=stat&sektion=1">bsds <code>stat</code></a> (2002):</p> <pre><code>stat -f %z -- "$file" # st_size of file stat -lf %z -- "$file" # after symlink resolution </code></pre></li> </ul><p>или вы можете использовать функцию <code>stat()</code>/<code>lstat()</code> некоторого языка сценариев, например <code>perl</code>:</p><pre><code>perl -le 'print((lstat shift)[7])' -- "$file" aix также имеет <a href="https://www.ibm.com/support/knowledgecenter/ssw_aix_72/com.ibm.aix.cmds3/istat.htm">istat command , которая будет сбрасывать всю информацию stat() (не lstat(), поэтому не будет работать с символическими ссылками) и который вы могли бы обработать, например:lc_all=c istat "$file" | awk 'nr == 4 {print $5}' (спасибо @jeffschaller за <a href="//chat.stackexchange.com/rooms/48172">помогите разобраться в деталях ).в tcsh:@ size = -z $file:q </code></pre><p>(размер после разрешения символической ссылки)</p><p>задолго до того, как gnu представило свою команду <code>stat</code>, того же можно добиться с помощью команды gnu <code>find</code> с предикатом <code>-printf</code>) ( уже в 1991 году)</p><pre><code>find -- "$file" -prune -printf '%sn' # st_size of file find -l -- "$file" -prune -printf '%s\n' # after symlink resolution </code></pre><p>однако одна проблема заключается в том, что не работает, если <code>$file начинается с - или является предикатом find (например, !, (...).стандартная команда для получения информации stat()/lstat() ls.posixly, вы можете сделать: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" </code></pre><p>однако для этого вам нужно разрешение на чтение файла устройства. обычно можно получить размер другими способами. например (все еще в linux):</p><pre><code>lsblk -bdno size -- "$device_file" должно работать за исключением пустых устройств.подход, который работает для всех  файлов с возможностью поиска  (включая обычные файлы, большинство блочных устройств и некоторые символьные устройства), заключается в открытии файла и поиске до конца. :  с zsh (после загрузки модуля zsh/system): {sysseek -w end 0 && size=$((systell(0)))} < $file   с ksh93: < "$file" <#((size=eof)) </code></pre> <p>или</p> <pre><code>{ size=$(<#((eof))); } < "$file" </code></pre></li> <li> <p>с <code>perl</code>:</p> <pre><code>perl -le 'seek stdin, 0, 2 or die "seek: $!"; print tell stdin' < "$file" </code></pre></li> </ul><p>для именованных каналов мы видели, что некоторые системы (по крайней мере, aix, solaris, hp/ux) предоставляют объем данных в буфере канала, доступный в <code>stat()</code> <code>st\_size</code>. некоторые (например, linux или freebsd) этого не делают.</p><p>по крайней мере, в linux вы можете использовать <code>fionread</code> <code>ioctl()</code> после открытия канала (в режиме чтения + записи, чтобы избежать его зависания):</p><pre><code>fuser -s -- "$fifo_file" && perl -le 'require "sys/ioctl.ph"; ioctl(stdin, &fionread, $n) or die$!; print unpack "l", $n' <> "$fifo_file" однако обратите внимание, что хотя он не  читает  содержимое канала, простое открытие именованного канала может иметь побочные эффекты. мы используем fuser, чтобы сначала проверить, что у какого-то процесса уже есть открытый канал, чтобы облегчить это, но это не надежно, поскольку fuser не сможет проверить все процессы.итак, до сих пор мы рассматривали только размер  первичных  данных, связанных с файлами. это не учитывает размер метаданных и всю вспомогательную инфраструктуру, необходимую для хранения этого файла.другой атрибут inode, возвращаемый stat(), это st_blocks. это количество блоков размером 512 байт, которое используется для хранения данных файла (а иногда и некоторых его метаданных, таких как расширенные атрибуты в файловых системах ext4 в linux). это не включает сам индекс, или записи в каталогах, с которыми связан файл.размер и использование диска не обязательно тесно связаны как сжатие, разреженность (иногда некоторые метаданные), дополнительная инфраструктура, например косвенные блоки в некоторых файловых системах, влияют на последнюю.это обычно то, что du использует, чтобы сообщить об использовании диска. большинство команд, перечисленных выше, смогут получить эту информацию. posixly_correct=1 ls -sd -- "$file" | awk '{print $1; exit}' posixly_correct=1 du -s -- "$file"</code> (не для каталогов, где это будет включать в себя использование диска файлов внутри).</li> <li>gnu <code>find -- "$file" -printf '%bn' zstat -l +block -- $file</code></li> <li>gnu <code>stat -c %b -- "$file" bsd stat -f %b -- "$file"</code></li> <li><code>perl -le 'print((lstat shift)[12])' -- "$file" 

этот скрипт объединяет множество способов расчета размера файла:( 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 и т.д.размер файла показывает количество байтов. это очевидный размер, который представляет собой байты, которые файл использует на типичном диске, без специального сжатия, специальных разреженных областей, нераспределенных блоков и т.д.этот скрипт имеет производственную версию с дополнительной справкой и дополнительными опциями здесь: <a href="https://github.com/sixarm/file-size">https://github.com/sixarm/file-size 

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 </code></pre>

<p><code>ls -l filename</code> предоставит вам много информации о файле, включая его размер, права доступа и владельца.</p><p>размер файла в пятом столбце и отображается в байтах. в приведенном ниже примере размер файла составляет чуть менее 2 кб:</p><pre><code>-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php </code></pre><p><strong>edit:</strong> это, очевидно, не так надежно, как команда <code>stat</code>.</p>

<p><code>du filename</code> сообщит вам об использовании диска в байтах.</p><p>я предпочитаю <code>du -h filename</code>, который дает вам размер в удобочитаемом формате.</p>

<p>я нашел вкладыш awk 1, и в нем была ошибка, но я исправил ее. я также добавил в petabytes после terabytes.</p><pre><code>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] }') учитывая, что <strong>stat</strong> не в каждой системе, вы почти всегда можете использовать решение awk. пример; raspberry pi не имеет <strong>stat</strong>, но имеет <strong>awk</strong>.

создайте в своих сценариях shell небольшие служебные функции, которым вы можете делегировать.пример#! /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 основано на информации из ответа стефана шазеля.

еще один способ, совместимый с posix, заключается в использовании awk с его функцией length(), которая возвращает длину в символах в каждой строке входного файла, исключая символы новой строки. итак, делая_awk '{ sum+=length } end { print sum+nr }' file _мы гарантируем, что nr добавляется к sum, что приводит к общему количеству символов и общему количеству строк, встречающихся в файле. функция length() в awk принимает аргумент, который по умолчанию означает length($0)</code> для текущей целой строки.</p>