В 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 команды, чтобы сделать то же самое?
Ответы:
wc -c < filename
(сокращение от word count,-c
печатает количество байтов) - это портативное решение POSIX . Только выходной формат может быть неоднородным для разных платформ, поскольку некоторые пробелы могут быть добавлены в начале (как в случае с Solaris).Не пропускайте перенаправление ввода. Когда файл передается в качестве аргумента, имя файла печатается после счетчика байтов.
Я волновался, что это не сработает для двоичных файлов, но работает нормально как на Linux, так и на Solaris. Вы можете попробовать
wc -c < /usr/bin/wc
. Более того, утилиты POSIX гарантированно обрабатывают двоичные файлы , если явно не указано иное.источник
wc -c < file
если вы не хотите, чтобы имя файла отображалось.wc
в конвейере долженread()
весь поток считать байты. Вls
/awk
решения (и подобные) используют системный вызов , чтобы получить размер, который должен быть линейное время ( по сравнению с O (размер))wc
как в последний раз я делал это на полном жестком диске очень медленно. Это было достаточно медленно, чтобы я мог переписать сценарий до того, как закончил первый, пришел сюда, чтобы вспомнить, как я это делал, лол.wc -c
; выглядит намного аккуратнее, ноls
+awk
лучше по скорости / использованию ресурсов. Кроме того, я просто хотел указать, что вам действительно нужноwc
постобработать результаты, потому что в некоторых системах перед результатом будут пробелы, которые вам может потребоваться удалить, прежде чем вы сможете проводить сравнения.wc -c
отлично, но он не будет работать, если у вас нет доступа для чтения к файлу.В итоге я написал свою собственную программу (действительно маленькую), чтобы отображать только размер. Дополнительная информация здесь: http://fwhacking.blogspot.com/2011/03/bfsize-print-file-size-in-bytes-and.html
На мой взгляд, два наиболее простых способа использования общих инструментов Linux:
Но я просто не хочу вводить параметры или передавать вывод только для того, чтобы получить размер файла, поэтому я использую свой собственный bfsize.
источник
stat
являются для них вариантом.wc -c
требует 4090 мсек для файла размером 10 МБ против «0» мсек дляstat -c %s
, поэтому я согласен, что полезно иметь альтернативные решения, даже если они не дают точного ответа на поставленный вопрос.stat -c %s /usr/bin/stat
stat: illegal option -- c
usage: stat [-FlLnqrsx] [-f format] [-t timefmt] [file ...]
Несмотря на то, что
du
обычно печатается использование диска, а не фактический размер данных, GNU coreutilsdu
может печатать «видимый размер» файла в байтах:Но он не будет работать под BSD, Solaris, macOS, ...
источник
brew install coreutils
иgdu -b
будет тот же эффектwc
для получения результата необходимоdu
немедленно прочитать весь файл .du -b
в совершенно другом контексте вdu
обосновании .lstat
вызов, поэтому его производительность не зависит от размера файла. Корочеstat -c '%s'
, но менее интуитивно понятен и работает по-разному для папок (печатает размер каждого файла внутри).du
может приблизиться к использованиюdu -A -B1
, но она по-прежнему выводит результат, кратный 1024B блокам. Не удалось заставить его печатать количество байтов. Даже установкаBLOCKSIZE=1
в environemnt не помогает, потому что тогда используется блок 512B.Наконец, я решил использовать ls и расширение массива bash:
это не очень хорошо, но, по крайней мере, он делает только 1 fork + execve, и он не полагается на вторичный язык программирования (perl / ruby / python / что-то еще)
источник
ls -ln FILE | { read _ _ _ _ size _ && echo "$size"; }
не нужен форк для второго этапа конвейера, поскольку он использует только встроенные модули, но Bash 4.2.37 на Linux форкует дважды (execve
хотя все еще только один ).read _ _ _ _ size _ <<<"$(exec ls -ln /usr/bin/wc)" && echo "$size"
работает с одиночным fork и single exec, но использует временный файл для данной строки. Его можно сделать переносимым, заменив строку здесь на POSX-совместимый документ . Кстати, обратите вниманиеexec
на подоболочку. Без этого Bash выполняет одну вилку для подоболочки, а другую - для выполняющейся внутри команды. Так обстоит дело с кодом, который вы предоставили в этом ответе. слишком.-l
наличии-n
. Цитирование POSIXls
справочной страницы :-n
: Включите-l
(еП) вариант, но при записи владельца файла или группы, запись числового UID файла или GID , а не имя пользователя или группы, соответственно. Отключить-C
,-m
и-x
варианты.Самое быстрое кроссплатформенное решение (использует только single fork () для ls , не пытается подсчитывать фактические символы, не создает ненужные awk, perl и т. Д.).
Проверено на MacOS, Linux - может потребоваться небольшая модификация для Solaris:
При необходимости упростите аргументы ls и отрегулируйте смещение в $ {__ ln [3]}.
Примечание: будет следовать символическим ссылкам.
источник
BSD имеют
stat
опции, отличные от GNU coreutils, но схожие возможности.Это работает на macOS (проверено 10.12), FreeBSD , NetBSD и OpenBSD .
источник
stat
утилиты.При обработке
ls -n
вывода в качестве альтернативы плохо переносимым массивам оболочки можно использовать позиционные аргументы, которые образуют единственный массив и являются единственными локальными переменными в стандартной оболочке. Оберните перезапись позиционных аргументов в функции, чтобы сохранить исходные аргументы вашего скрипта или функции.Это разделяет вывод в
ln -dn
соответствии с текущимиIFS
настройками переменной среды, назначает его позиционным аргументам и повторяет пятый. Это-d
гарантирует, что каталоги обрабатываются правильно, и-n
гарантирует, что имена пользователей и групп не нужно разрешать, в отличие от с-l
. Кроме того, имена пользователей и групп, содержащие пробелы, теоретически могут нарушить ожидаемую структуру строк; они обычно запрещены, но такая возможность все же заставляет программиста задуматься.источник
Если вы используете
find
GNU fileutils:К сожалению, другие реализации
find
обычно не поддерживают-maxdepth
, ни-printf
. Это относится, например, к Solaris и macOSfind
.источник
size=$(test -f filename && find filename -printf '%s')
.-maxdepth
предназначен для предотвращения рекурсииfind
(посколькуstat
OP, который необходимо заменить, не является). В вашейfind
команде отсутствует символ,-name
иtest
команда не нужна.find
рекурсивно ищет в своих параметрах файлы, соответствующие заданным критериям. Если параметры не каталоги, рекурсия… довольно проста. Поэтому я сначала проверяю, чтоfilename
это действительно существующий обычный файл, а затем распечатываю его размер, используяfind
то, что рекурсивно некуда.find . -maxdepth 1 -type f -name filename -printf '%s'
работает только в том случае, если файл находится в текущем каталоге, и он все еще может проверять каждый файл в каталоге, что может быть медленным. Лучше использовать (даже короче!)find filename -maxdepth 1 -type f -printf '%s'
.Вы можете использовать
find
команду, чтобы получить некоторый набор файлов (здесь извлекаются временные файлы). Затем вы можете использоватьdu
команду для получения размера каждого файла в удобочитаемой форме с помощью-h
переключателя.ВЫВОД:
источник
Ваш первый пример Perl не кажется мне необоснованным.
По таким причинам я перешел от написания сценариев оболочки (в bash / sh и т. Д.) К написанию всех, кроме самых тривиальных, сценариев на Perl. Я обнаружил, что мне нужно запускать Perl для определенных требований, и по мере того, как я делал это все чаще и чаще, я понял, что написание скриптов на Perl, вероятно, было более мощным (с точки зрения языка и широкого спектра библиотек, доступных через CPAN ) и более эффективный способ добиться того, чего я хотел.
Обратите внимание, что другие языки сценариев оболочки (например, python / ruby), несомненно, будут иметь аналогичные возможности, и вы можете оценить их для своих целей. Я обсуждаю только Perl, поскольку это язык, который я использую и с которым я знаком.
источник
если у вас есть Perl на вашем Solaris, используйте его. В противном случае следующий лучший выбор - ls с awk, так как у вас нет статистики или ваша find не является поиском GNU.
источник
В Solaris есть трюк, который я использовал: если вы запрашиваете размер более одного файла, он возвращает только общий размер без имен - поэтому включите пустой файл, например / dev / null, в качестве второго файла:
например, командный файл: вы хотите / dev / null
Я не могу вспомнить, какая команда размера работает для ls / wc / etc - к сожалению, у меня нет окна Solaris, чтобы проверить это.
источник
на linux вы можете использовать
du -h $FILE
, это работает и на solaris?источник
Вы пробовали du -ks | awk '{напечатать $ 1 * 1024}'. Это может сработать.
источник