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


107

Если я введу команду поиска следующим образом:

$ find . -name *.ear

Он распечатывает:

./dir1/dir2/earFile1.ear
./dir1/dir2/earFile2.ear
./dir1/dir3/earFile1.ear

Я хочу «напечатать» в командной строке имя и размер:

./dir1/dir2/earFile1.ear  5000 KB
./dir1/dir2/earFile2.ear  5400 KB
./dir1/dir3/earFile1.ear  5400 KB

Ответы:


110
find . -name '*.ear' -exec ls -lh {} \;

только h extra из ответа jer.drab.org. экономит время, мысленно конвертируя в МБ;)


8
Эта версия будет запускать процесс «ls» для каждого файла. Если у вас много файлов (скажем, более тысячи), лучше оптимизировать их: find . -name '*.ear' -exec ls -lh {} + \;(расширение GNU) или find . -name '*.ear' -print0 | xargs -0 ls -lh. Также вы можете добавить, -type fесли вас интересуют только файлы (или добавить -dв ls, если вы хотите, чтобы сами каталоги были включены без их содержимого).
ash108

2
Ваш ответ не исключает каталоги, поэтому в конечном итоге вы также запустите команду ls для каталогов, что явно неверно.
Faheem Mitha

2
Это действительно неэффективный способ решения задач - и, к сожалению, комментарии ash108 также не идеальны. Для поиска лучше использовать параметр -printf.
oskarpearson

Ответ dmazzoni намного эффективнее, потому что он избегает fork + exec для каждого файла (в 100 раз быстрее на моей машине). Мне пришлось сменить% k на% s. @FaheemMitha: вы можете добавить такие параметры, как -type fподсчет только обычных файлов.
Mr Fooz

@FaheemMitha простое решение find . -name "*.ear" -type fдля файлов. -type dработает для справочников.
anon58192932

112

Вам нужно использовать -exec или -printf. Printf работает так:

find . -name *.ear -printf "%p %k KB\n"

-exec более мощный и позволяет выполнять произвольные команды, поэтому вы можете использовать версию ls или wc для распечатки имени файла вместе с другой информацией. 'man find' покажет вам доступные аргументы printf, которые могут намного больше, чем просто размер файла.

[edit] -printf не входит в официальный стандарт POSIX, поэтому проверьте, поддерживается ли он в вашей версии. Однако большинство современных систем будут использовать GNU find или аналогичную расширенную версию, так что есть большая вероятность, что она будет реализована.


Похоже, ваш пример более точен, но я не могу заставить этот пример работать на Solaris 10.
Брайан

Боюсь, что Solaris find вообще не поддерживает -printf: jrwren.wrenfam.com/blog/2006/10/07/solaris-find-sucks cs.bgu.ac.il/~arik/usail/man/solaris/ find.1.html Вы можете установить GNU find, если вас это беспокоит, иначе вам нужно использовать exec или | как было предложено другими.
Ли Колдуэлл,

1
+1 Вроде чище. Чтобы отформатировать вывод, я бы предпочел добавить columnкоманду. find . -name *.ear -printf "%p %k KB\n" | column -t
Amol

1
Этот ответ - гораздо более правильный способ сделать это, чем принятый ответ
угрожающе

2
Эта -printfопция также не работает в OS X. См. Stackoverflow.com/questions/752818/… .
abeboparebop 07

33

простое решение - использовать параметр -ls в find:

find . -name \*.ear -ls

Это дает вам каждую запись в обычном формате "ls -l". Или, чтобы получить конкретный результат, который вы, кажется, ищете, это:

find . -name \*.ear -printf "%p\t%k KB\n"

Это даст вам имя файла, за которым следует размер в КБ.


Даже не знал о lsварианте, он должен быть намного выше в списке ответов, чем он есть.
Прометей

24

Используя gnu find, я думаю, это то, что вам нужно. Он находит все реальные файлы, а не каталоги (-тип f), и для каждого печатает имя файла (% p), табуляцию (\ t), размер в килобайтах (% k), суффикс «KB», а затем перевод строки (\ n).

find . -type f -printf '%p\t%k KB\n'

Если команда printf не форматирует вещи так, как вы хотите, вы можете использовать exec, а затем команду, которую вы хотите выполнить для каждого файла. Используйте {} в качестве имени файла и завершите команду точкой с запятой (;). В большинстве оболочек все три этих символа должны быть экранированы обратной косой чертой.

Вот простое решение, которое находит и распечатывает их с помощью "ls -lh", который покажет вам размер в удобочитаемой форме (k для килобайт, M для мегабайт):

find . -type f -exec ls -lh \{\} \;

В качестве еще одной альтернативы "wc -c" напечатает количество символов (байтов) в файле:

find . -type f -exec wc -c \{\} \;

+1 За исключением того, что он пропущен -name '*.ear'в примерах, это должен быть ответ №1. Он точно отвечает на вопрос, объясняет значение синтаксиса и дает несколько альтернатив.
OsakaWebbie

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

В самом деле, это должен быть правильный ответ. Кроме того, find . -type f -printf '%k KB\t %p\n'то есть сначала распечатать размер файла, скорее всего, будет лучше с точки зрения форматирования из-за выравнивания.
myradio

8
find . -name '*.ear' -exec du -h {} \;

Это дает вам только размер файла вместо всего ненужного.


wcработает для этого лучше, если вам нужен размер в байтах.
Alex

4

Awk может исправить вывод, чтобы дать именно то, о чем спрашивал спрашивающий. В моей системе Solaris 10 команда find -ls выводит размер в КБ во втором поле, поэтому:

% find . -name '*.ear' -ls | awk '{print $2, $11}'
5400 ./dir1/dir2/earFile2.ear
5400 ./dir1/dir2/earFile3.ear
5400 ./dir1/dir2/earFile1.ear

В противном случае используйте -exec ls -lh и выберите поле размера из вывода. Снова в Solaris 10:

% find . -name '*.ear' -exec ls -lh {} \; | awk '{print $5, $9}'
5.3M ./dir1/dir2/earFile2.ear
5.3M ./dir1/dir2/earFile3.ear
5.3M ./dir1/dir2/earFile1.ear

4

Почему бы не использовать ду-а ? Например

find . -name "*.ear" -exec du -a {} \;

Работает на Mac


3

Я боролся с этим в Mac OS X, где команда find не поддерживает -printf.

Решение, которое я нашел, которое, по общему признанию, полагается на «группу» для всех файлов, являющихся «персоналом», было ...

ls -l -R | sed 's/\(.*\)staff *\([0-9]*\)..............\(.*\)/\2 \3/'

Это разбивает вывод ls long на три токена

  1. материал перед текстом "персонал"
  2. размер файла
  3. имя файла

Затем выводятся токены 2 и 3, т.е. вывод - это количество байтов, а затем имя файла

8071 sections.php
54681 services.php
37961 style.css
13260 thumb.php
70951 workshops.php

1
Полезно знать .. Версия GNU findдоступна через homebrew сbrew install findutils
mwfearnley

2

Это должно дать вам то, что вы ищете, включая форматирование (т.е. сначала имя файла, а затем размер):

find . -type f -iname "*.ear" -exec du -ah {} \; | awk '{print $2"\t", $1}'

пример вывода (где я раньше -iname "*.php"получал какой-то результат):

./plugins/bat/class.bat.inc.php  20K
./plugins/quotas/class.quotas.inc.php    8.0K
./plugins/dmraid/class.dmraid.inc.php    8.0K
./plugins/updatenotifier/class.updatenotifier.inc.php    4.0K
./index.php      4.0K
./config.php     12K
./includes/mb/class.hwsensors.inc.php    8.0K

2

Попробуйте следующие команды:

GNU stat:

find . -type f -name *.ear -exec stat -c "%n %s" {} ';'

BSD stat:

find . -type f -name *.ear -exec stat -f "%N %z" {} ';'

однако statне является стандартным, так duи wcможет быть лучшим подходом:

find . -type f -name *.ear -exec sh -c 'echo "{} $(wc -c < {})"' ';'

1

Вы можете попробовать это:

find. -name *.ear -exec du {} \;

Это даст вам размер в байтах. Но команда du также принимает параметры -k для КБ и -m для МБ. Это даст вам результат вроде

5000  ./dir1/dir2/earFile1.ear
5400  ./dir1/dir2/earFile2.ear
5400  ./dir1/dir3/earFile1.ear




0

Если вам нужно получить общий размер, вот предложение сценария

#!/bin/bash
totalSize=0

allSizes=`find . -type f -name *.ear -exec stat -c "%s" {} \;`

for fileSize in $allSizes; do
    totalSize=`echo "$(($totalSize+$fileSize))"`
done
echo "Total size is $totalSize bytes"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.