Como faço para que o comando find imprima o tamanho do arquivo com o nome do arquivo?

106

Se eu emitir o comando find da seguinte maneira:

$ find . -name *.ear

Ele imprime:

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

O que eu quero 'imprimir' na linha de comando é o nome e o tamanho:

./dir1/dir2/earFile1.ear  5000 KB
./dir1/dir2/earFile2.ear  5400 KB
./dir1/dir3/earFile1.ear  5400 KB
Brian Hart
fonte

Respostas:

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

apenas um extra da resposta de jer.drab.org. economiza tempo convertendo mentalmente para MB;)

tímido
fonte
8
Esta versão executará o processo "ls" para cada arquivo. Se você tiver muitos arquivos (digamos, mais de mil), é melhor otimizá-los com: find . -name '*.ear' -exec ls -lh {} + \;(extensão GNU) ou find . -name '*.ear' -print0 | xargs -0 ls -lh. Além disso, você pode adicionar -type fse estiver interessado apenas em arquivos (ou adicionar -da ls se quiser que os próprios diretórios sejam incluídos sem seu conteúdo).
ash108
2
Sua resposta não exclui diretórios, portanto, você também executará ls em diretórios, o que claramente não é a coisa certa a se fazer.
Faheem Mitha
2
Esta é uma maneira realmente ineficiente de fazer as coisas - e infelizmente os comentários do ash108 também não são ideais. É muito melhor usar a opção -printf para localizar.
oskarpearson
A resposta do dmazzoni é muito mais eficiente porque evita um fork + exec em cada arquivo (100x mais rápido na minha máquina). Tive que mudar% k para% s. @FaheemMitha: você pode adicionar opções como -type fcontar apenas arquivos regulares.
Sr. Fooz
A solução fácil @FaheemMitha é find . -name "*.ear" -type fpara arquivos. -type dfunciona para diretórios.
anon58192932
111

Você precisa usar -exec ou -printf. Printf funciona assim:

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

-exec é mais poderoso e permite que você execute comandos arbitrários - então você pode usar uma versão de 'ls' ou 'wc' para imprimir o nome do arquivo junto com outras informações. 'man find' mostrará os argumentos disponíveis para printf, que pode fazer muito mais do que apenas o tamanho do arquivo.

[editar] -printf não está no padrão POSIX oficial, então verifique se ele é compatível com sua versão. No entanto, a maioria dos sistemas modernos usará GNU find ou uma versão estendida de forma semelhante, então há uma boa chance de que seja implementado.

Leigh Caldwell
fonte
Parece que seu exemplo é mais preciso, mas não consigo fazer com que o exemplo funcione no Solaris 10.
Brian,
Infelizmente, o Solaris find não oferece suporte a -printf: jrwren.wrenfam.com/blog/2006/10/07/solaris-find-sucks cs.bgu.ac.il/~arik/usail/man/solaris/ find.1.html Você pode instalar o GNU find se for incomodado; caso contrário, será necessário usar exec ou | como sugerido por outros.
Leigh Caldwell,
1
+1 Isso parece mais limpo. Para formatar a saída, prefiro adicionar o columncomando. find . -name *.ear -printf "%p %k KB\n" | column -t
Amol
1
Esta resposta é uma maneira muito mais correta de fazer isso do que a resposta aceita
ameaçadoramente
2
A -printfopção não funciona no OS X também. Consulte stackoverflow.com/questions/752818/… .
abeboparebop
33

uma solução simples é usar a opção -ls em find:

find . -name \*.ear -ls

Isso dá a você cada entrada no formato normal "ls -l". Ou, para obter a saída específica que você parece estar procurando, isto:

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

O que fornecerá o nome do arquivo seguido pelo tamanho em KB.

Michael Cramer
fonte
Nem sabia de uma lsopção, isso deveria estar muito mais alto na lista de respostas do que é.
Prometheus de
24

Usando gnu find, acho que é isso que você quer. Ele encontra todos os arquivos reais e não os diretórios (-type f), e para cada um imprime o nome do arquivo (% p), uma guia (\ t), o tamanho em kilobytes (% k), o sufixo "KB" e então uma nova linha (\ n).

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

Se o comando printf não formatar as coisas da maneira que você deseja, você pode usar exec, seguido pelo comando que deseja executar em cada arquivo. Use {} para o nome do arquivo e termine o comando com um ponto e vírgula (;). Na maioria dos shells, todos os três desses caracteres devem ser escapados com uma barra invertida.

Aqui está uma solução simples que os encontra e os imprime usando "ls -lh", que mostrará o tamanho em formato legível (k para kilobytes, M para megabytes):

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

Como outra alternativa, "wc -c" imprimirá o número de caracteres (bytes) no arquivo:

find . -type f -exec wc -c \{\} \;
dmazzoni
fonte
+1 Exceto por ter omitido -name '*.ear'nos exemplos, esta deve ser a resposta nº 1. Ele responde à pergunta com precisão, explica o significado da sintaxe e oferece várias alternativas.
OsakaWebbie
esta deve ser uma resposta aceita, pois não executa um novo comando para cada linha, portanto, é muito mais rápido do que o atualmente aceito por shyam
jirislav
Na verdade, esta deve ser a resposta certa. Além disso, find . -type f -printf '%k KB\t %p\n'ou seja, imprimir o tamanho do arquivo primeiro, provavelmente será uma saída melhor em termos de formatação devido ao alinhamento.
myradio
8
find . -name '*.ear' -exec du -h {} \;

Isso dá a você apenas o tamanho do arquivo, em vez de todas as coisas desnecessárias.

user2121791
fonte
wcfunciona melhor para isso, se você precisar do tamanho em bytes.
Alex
4

Awk pode consertar a saída para fornecer exatamente o que o questionador pediu. No meu sistema Solaris 10, encontre -ls tamanho das impressões em KB como o segundo campo, portanto:

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

Caso contrário, use -exec ls -lh e selecione o campo de tamanho da saída. Novamente no 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
tpgould
fonte
4

Por que não usar du -a ? Por exemplo

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

Funciona em um Mac

sietschie
fonte
3

Tive dificuldade com isso no Mac OS X, onde o comando find não é compatível -printf.

Uma solução que encontrei, que confia reconhecidamente no 'grupo' para todos os arquivos serem 'equipe' foi ...

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

Isso divide a saída ls long em três tokens

  1. as coisas antes do texto 'pessoal'
  2. o tamanho do arquivo
  3. o nome do arquivo

E então gera os tokens 2 e 3, ou seja, a saída é o número de bytes e o nome do arquivo

8071 sections.php
54681 services.php
37961 style.css
13260 thumb.php
70951 workshops.php
Mike M
fonte
1
Útil saber .. A versão GNU do findestá disponível através do homebrew combrew install findutils
mwfearnley
2

Isso deve fornecer o que você está procurando, incluindo a formatação (ou seja, o nome do arquivo primeiro e o tamanho depois):

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

saída de amostra (onde costumava -iname "*.php"obter alguns resultados):

./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
adriano72
fonte
1

Você pode tentar isto:

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

Isso lhe dará o tamanho em bytes. Mas o comando du também aceita os parâmetros -k para KB e -m para MB. Isso lhe dará uma saída como

5000  ./dir1/dir2/earFile1.ear
5400  ./dir1/dir2/earFile2.ear
5400  ./dir1/dir3/earFile1.ear
Yaba
fonte
1
find . -name "*.ear" | xargs ls -sh
killdash10
fonte
1
$ find. -name "test *" -exec du -sh {} \;
4,0K ./teste1
0 ./test2
0 ./test3
0 ./test4
$

Referência do Scripter World

scripter
fonte
1

Experimente os seguintes comandos:

GNU stat:

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

BSD stat:

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

no entanto, statnão é padrão, então duou wcpoderia ser uma abordagem melhor:

find . -type f -name *.ear -exec sh -c 'echo "{} $(wc -c < {})"' ';'
Kenorb
fonte
0
find . -name "*.ear" -exec ls -l {} \;
Jeremy Weathers
fonte
0

Se você precisa obter o tamanho total, aqui está uma proposta de script

#!/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"
Damien C
fonte