Come ottengo il comando find per stampare la dimensione del file con il nome del file?


106

Se emetto il comando find come segue:

$ find . -name *.ear

Stampa:

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

Quello che voglio 'stampare' sulla riga di comando è il nome e la dimensione:

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

Risposte:


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

solo il h extra dalla risposta di jer.drab.org. fa risparmiare tempo nella conversione in MB mentalmente;)


8
Questa versione eseguirà il processo "ls" per ogni file. Se hai molti file (diciamo più di un migliaio) è meglio ottimizzarli con: find . -name '*.ear' -exec ls -lh {} + \;(estensione GNU) o find . -name '*.ear' -print0 | xargs -0 ls -lh. Inoltre potresti voler aggiungere -type fse sei interessato solo ai file (o aggiungere -da ls se vuoi che le directory stesse siano incluse senza il loro contenuto).
— ash108

2
La tua risposta non esclude le directory, quindi finirai per eseguire ls anche sulle directory, il che chiaramente non è la cosa giusta da fare.
— Faheem Mitha

2
Questo è un modo davvero inefficiente di fare le cose - e sfortunatamente anche i commenti di ash108 non sono ideali. È molto meglio usare l'opzione -printf per trovare.
— oskarpearson

La risposta di dmazzoni è molto più efficiente perché evita un fork + exec su ogni file (100 volte più veloce sulla mia macchina). Ho dovuto cambiare% k in% s. @FaheemMitha: puoi aggiungere opzioni come -type fcontare solo i file normali.
— Mr Fooz,

@FaheemMitha soluzione facile è find . -name "*.ear" -type fper i file. -type dfunziona per le directory.
— anon58192932

111

È necessario utilizzare -exec o -printf. Printf funziona in questo modo:

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

-exec è più potente e consente di eseguire comandi arbitrari, quindi è possibile utilizzare una versione di "ls" o "wc" per stampare il nome del file insieme ad altre informazioni. 'man find' ti mostrerà gli argomenti disponibili per printf, che può fare molto di più della semplice dimensione del file.

[modifica] -printf non è nello standard POSIX ufficiale, quindi controlla se è supportato sulla tua versione. Tuttavia, la maggior parte dei sistemi moderni utilizzerà GNU find o una versione estesa in modo simile, quindi ci sono buone probabilità che venga implementata.


Sembra che il tuo esempio sia più preciso, ma non riesco a far funzionare l'esempio su Solaris 10.
— Brian

Temo che Solaris find non supporti affatto -printf : jrwren.wrenfam.com/blog/2006/10/07/solaris-find-sucks cs.bgu.ac.il/~arik/usail/man/solaris/ find.1.html Potresti installare GNU find se puoi essere disturbato, altrimenti devi usare exec o | come suggerito da altri.
— Leigh Caldwell,

1
+1 Sembra più pulito. Per formattare l'output preferirei aggiungere il columncomando. find . -name *.ear -printf "%p %k KB\n" | column -t
— Amol

1
Questa risposta è un modo molto più corretto per farlo rispetto alla risposta accettata
— minacciosamente il

2
L' -printfopzione non funziona neanche in OS X. Vedi stackoverflow.com/questions/752818/… .
— abeboparebop

33

una soluzione semplice è usare l'opzione -ls in find:

find . -name \*.ear -ls

Questo ti dà ogni voce nel normale formato "ls -l". Oppure, per ottenere l'output specifico che sembri cercare, questo:

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

Che ti darà il nome del file seguito dalla dimensione in KB.


Non sapevo nemmeno lsun'opzione, questa dovrebbe essere molto più in alto nell'elenco delle risposte di quanto non sia.
— Prometeo il

24

Usando gnu find, penso che questo sia quello che vuoi. Trova tutti i file reali e non le directory (-type f), e per ognuno stampa il nome del file (% p), una tabulazione (\ t), la dimensione in kilobyte (% k), il suffisso "KB" e poi una nuova riga (\ n).

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

Se il comando printf non formatta le cose nel modo desiderato, puoi usare exec, seguito dal comando che vuoi eseguire su ogni file. Usa {} per il nome del file e termina il comando con un punto e virgola (;). Sulla maggior parte delle shell, tutti e tre questi caratteri dovrebbero essere sottoposti a escape con una barra rovesciata.

Ecco una semplice soluzione che li trova e li stampa usando "ls -lh", che ti mostrerà la dimensione in forma leggibile dall'uomo (k per kilobyte, M per megabyte):

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

Come ancora un'altra alternativa, "wc -c" stamperà il numero di caratteri (byte) nel file:

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

+1 Ad eccezione di aver omesso -name '*.ear'negli esempi, questa dovrebbe essere la risposta n. 1. Risponde con precisione alla domanda, spiega il significato della sintassi e offre più alternative.
— OsakaWebbie

questa dovrebbe essere una risposta accettata in quanto non esegue un nuovo comando per ogni riga, quindi è molto più veloce di quello attualmente accettato da shyam
— jirislav

In effetti questa dovrebbe essere la risposta giusta. Inoltre, ad find . -type f -printf '%k KB\t %p\n'esempio, stampare prima la dimensione del file, molto probabilmente sarà un risultato migliore in termini di formattazione a causa dell'allineamento.
— myradio

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

Questo ti dà solo la dimensione del file, invece di tutte le cose non necessarie.


wcfunziona per questo solo meglio, se hai bisogno della dimensione in byte.
— Alex

4

Awk può correggere l'output per fornire esattamente ciò che l'interrogante ha chiesto. Sul mio sistema Solaris 10, trova -ls stampa la dimensione in KB come secondo campo, quindi:

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

Altrimenti, usa -exec ls -lh e scegli il campo delle dimensioni dall'output. Di nuovo su 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

Perché non usare du -a ? Per esempio

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

Funziona su un Mac


3

Ho lottato con questo su Mac OS X dove il comando find non supporta -printf.

Una soluzione che ho trovato, che certamente si basa sul "gruppo" per tutti i file che sono "staff" è stata ...

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

Questo divide l'output lungo di ls in tre token

  1. le cose prima del testo "staff"
  2. la dimensione del file
  3. il nome del file

E poi restituisce i token 2 e 3, ovvero l'output è il numero di byte e quindi il nome del file

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

1
Utile da sapere .. La versione GNU di findè disponibile tramite homebrew conbrew install findutils
— mwfearnley

2

Questo dovrebbe darti quello che stai cercando, inclusa la formattazione (cioè il nome del file prima e la dimensione dopo):

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

output di esempio (dove ho usato -iname "*.php"per ottenere qualche risultato):

./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

1

Potresti provare questo:

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

Questo ti darà la dimensione in byte. Ma il comando du accetta anche i parametri -k per KB e -m per MB. Ti darà un output come

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



1

Prova i seguenti comandi:

GNU stat:

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

BSD stat:

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

tuttavia statnon è standard, quindi duo wcpotrebbe essere un approccio migliore:

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


0

Se hai bisogno di ottenere la dimensione totale, ecco una proposta di 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"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.