Портативный способ получить размер файла (в байтах) в оболочке?

В Linux я использую stat --format="%s" FILE, но у Solaris у меня есть доступ к команде stat. Что мне тогда использовать?

Я пишу сценарии Bash и не могу установить какое-либо новое программное обеспечение в системе.

Я уже использовал:

perl -e '@x=stat(shift);print $x[7]' FILE

или даже:

ls -nl FILE | awk '{print $5}'

Но ни один из них не выглядит разумным - запуск Perl только для получения размера файла? Или запустите 2 команды, чтобы сделать то же самое?

Ответ 2

В итоге я написал свою собственную программу (очень маленькую), чтобы отображать только размер. Дополнительная информация здесь: http://fwhacking.blogspot.com/2011/03/bfsize-print-file-size-in-bytes-and.html

Два самых чистых способа, на мой взгляд, с обычными инструментами Linux:

$ stat -c %s /usr/bin/stat
50000

$ wc -c < /usr/bin/wc
36912

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

Ответ 3

Даже если du обычно печатает использование диска, а не фактический размер данных, GNU coreutils du может печатать файл "видимый размер" в байтах:

du -b FILE

Но он не будет работать под BSD, Solaris, macOS,...

Ответ 4

Наконец, я решил использовать расширение ls и bash:

TEMP=( $( ls -ln FILE ) )
SIZE=${TEMP[4]}

это не очень хорошо, но по крайней мере он делает только 1 fork + execve и не полагается на вторичный язык программирования (perl/ruby ​​/python/whatever)

Ответ 5

Самое быстрое решение кросс-платформы (использует только single fork() для ls, не пытается подсчитать действительные символы, не создает ненужных awk, perl и т.д.).

Протестировано на MacOS, Linux - может потребоваться незначительная модификация для Solaris:

__ln=( $( ls -Lon "$1" ) )
__size=${__ln[3]}
echo "Size is: $__size bytes"

При необходимости упростите аргументы ls и отрегулируйте смещение в ${__ ln [3]}.

Примечание: будут следовать символическим ссылкам.

Ответ 6

У BSD есть stat с разными опциями из GNU coreutils one, но с аналогичными возможностями.

stat -f %z <file name> 

Это работает на macOS (проверено 10.12), FreeBSD, NetBSD и OpenBSD.

Ответ 7

Вы можете использовать команду find для получения некоторого набора файлов (здесь распаковываются временные файлы). Затем вы можете использовать команду du, чтобы получить размер файла для каждого файла в удобочитаемой форме с помощью переключателя -h.

find $HOME -type f -name "*~" -exec du -h {} \;

ВЫВОД:

4.0K    /home/turing/Desktop/JavaExmp/TwoButtons.java~
4.0K    /home/turing/Desktop/JavaExmp/MyDrawPanel.java~
4.0K    /home/turing/Desktop/JavaExmp/Instream.java~
4.0K    /home/turing/Desktop/JavaExmp/RandomDemo.java~
4.0K    /home/turing/Desktop/JavaExmp/Buff.java~
4.0K    /home/turing/Desktop/JavaExmp/SimpleGui2.java~

Ответ 8

При обработке вывода ls -n в качестве альтернативы плохо переносимым массивам оболочки вы можете использовать позиционные аргументы, которые образуют единственный массив и являются единственными локальными переменными в стандартной оболочке. Оберните перезапись позиционных аргументов в функции, чтобы сохранить исходные аргументы в вашей script или функции.

getsize() { set -- $(ls -dn "$1") && echo $5; }
getsize FILE

Это разделяет вывод ln -dn в соответствии с текущими настройками переменных среды IFS, присваивает его позиционным аргументам и повторяет пятый. -d обеспечивает правильную обработку каталогов, а -n гарантирует, что имена пользователей и групп не должны быть разрешены, в отличие от -l. Кроме того, имена пользователей и групп, содержащие пробелы, могут теоретически нарушить ожидаемую структуру строки; они обычно запрещены, но эта возможность все еще заставляет программиста остановиться и подумать.

Ответ 9

Первый пример Perl для меня не выглядит необоснованным.

По причинам, подобным этому, я перешел от написания сценариев оболочки (в bash/sh и т.д.) для записи всех, кроме самых тривиальных скриптов в Perl. Я обнаружил, что мне приходится запускать Perl для определенных требований, и, когда я делал это все больше и больше, я понял, что сценарии на Perl, вероятно, были более мощными (с точки зрения языка и широкого набора библиотек, доступных через CPAN) и более эффективным способом достижения желаемого.

Обратите внимание, что другие языки скриптинга (например, python/ruby), без сомнения, будут иметь аналогичные возможности, и вы можете оценить их для своих целей. Я только обсуждаю Perl, так как язык, который я использую и знакомый.

Ответ 10

Как насчет du -s <file>?

Ответ 11

Если вы используете find из GNU fileutils:

size=$( find . -maxdepth 1 -type f -name filename -printf '%s' )

К сожалению, другие реализации find обычно не поддерживают -maxdepth, а не -printf. Это относится, например, к примеру. Solaris и macOS find.

Ответ 12

если у вас есть Perl на Solaris, а затем используйте его. В противном случае, ls с awk - ваш лучший лучший выбор, так как у вас нет статистики или ваша находка не найдена GNU.

Ответ 13

В Solaris, который я использовал, есть трюк, если вы запрашиваете размер более одного файла, он возвращает только общий размер без имен, поэтому включите пустой файл, например /dev/null, в качестве второго файла:

например,   команда fileyouwant/dev/null

Я не могу вспомнить, какая команда размера работает для ls/wc/etc - к сожалению, у меня нет камеры Solaris, чтобы проверить ее.

Ответ 14

на linux вы можете использовать du -h $FILE, это тоже работает на солярии?

Ответ 15

Вы попробовали du ​​-ks | awk '{print $1 * 1024}'. Это может сработать.