Comment puis-je obtenir la taille d'un fichier dans un script bash?
Comment puis-je l'affecter à une variable bash afin de pouvoir l'utiliser plus tard?
pv
et cat
pour une commande de copie qui montre le progrès et l' ETA :)
Comment puis-je obtenir la taille d'un fichier dans un script bash?
Comment puis-je l'affecter à une variable bash afin de pouvoir l'utiliser plus tard?
pv
et cat
pour une commande de copie qui montre le progrès et l' ETA :)
Réponses:
Votre meilleur pari si sur un système GNU:
stat --printf="%s" file.any
De l' homme stat :
% s taille totale, en octets
Dans un script bash:
#!/bin/bash
FILENAME=/home/heiko/dummy/packages.txt
FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."
REMARQUE: voir la réponse de @ chbrown pour savoir comment utiliser stat dans un terminal sous Mac OS X.
stat
est la méthode la plus simple, si vous utilisez Linux ou Cygwin (ce stat
n'est pas standard). wc -c
comme suggéré par Eugéne est portable.
stat: illegal option -- c
stat --printf="%s" file.txt
Ne donne rien sur Debian Jessie ...
stat -f%z myfile.tar
man stat
dit que --printf omet le retour à la ligne final. Utilisez --format
ou -c
pour voir la sortie. Gagnez en perspicacité en comparant stat --printf="%s" file.any | xxd -
àstat -c "%s" file.any | xxd -
file_size_kb=`du -k "$filename" | cut -f1`
Le problème de l'utilisation stat
est qu'il s'agit d'une extension GNU (Linux). du -k
et cut -f1
sont spécifiés par POSIX et sont donc portables sur tout système Unix.
Solaris, par exemple, est livré avec bash mais pas avec stat
. Donc, ce n'est pas entièrement hypothétique.
ls
Le problème est similaire: le format exact de la sortie n’est pas spécifié. Par conséquent, l’analyse de la sortie ne peut pas être effectuée de manière portable. du -h
est aussi une extension GNU.
Si possible, respectez les constructions portables et vous faciliterez la vie de quelqu'un à l'avenir. Peut-être la vôtre.
du
ne donne pas la taille du fichier, mais donne une indication de la quantité d’espace utilisé par le fichier, ce qui est légèrement différent (généralement, la taille indiquée par du
est la taille du fichier arrondie au nombre de blocs le plus proche, où un bloc est typiquement 512B ou 1KB ou 4KB).
--bytes
ou -b
au lieu de -k
, devrait être la réponse acceptée.
-h
option ("humaine") dedu
produira la réponse la plus appropriée pour les cas généraux:, file_size=`du -h "$filename" | cut -f1
car elle affichera K (kilo-octets), M (mégaoctets) ou G (gigaoctets) selon le cas.
Vous pouvez également utiliser la commande "nombre de mots" ( wc
):
wc -c "$filename" | awk '{print $1}'
Le problème avec wc
est qu'il va ajouter le nom de fichier et indenter la sortie. Par exemple:
$ wc -c somefile.txt
1160 somefile.txt
Si vous souhaitez éviter de chaîner un langage interprété complet ou un éditeur de flux uniquement pour obtenir un décompte de la taille du fichier, redirigez simplement l'entrée du fichier afin que wc
le nom de fichier ne soit jamais visible:
wc -c < "$filename"
Cette dernière forme peut être utilisée avec la substitution de commande pour saisir facilement la valeur recherchée en tant que variable shell, comme mentionné par Gilles ci-dessous.
size="$(wc -c <"$filename")"
wc -c <"$FILENAME"
donne la taille sans autre crue, donc size=$(wc -c <"$FILENAME")
.
wc -c < file
semble être très rapide, du moins sous OS X. J'imagine que wc a le cerveau pour essayer de stater le fichier si seulement -c est spécifié.
wc -c
utilise fstat
, mais cherche ensuite à l'avant dernier bloc du fichier et lit les derniers st_blksize
octets. Apparemment , c'est parce que les fichiers de Linux /proc
et /sys
par exemple ont des tailles de stat qui ne sont approximatifs , et wc
veut faire rapport à la taille réelle, pas la taille indiquée stat. J'imagine que ce serait bizarre wc -c
de signaler une taille différente de wc
, mais ce n'est pas une idée de lire les données du fichier s'il s'agit d'un fichier de disque normal, et ce n'est pas en mémoire. Ou pire, stockage sur bande proche de la ligne ...
printf
l’indentation est toujours visible, par exemple printf "Size: $size"
-> size: <4 spaces> 54339
. D'autre part echo
ignore les espaces blancs. Un moyen de le rendre cohérent?
fstat
. Essayez de courir strace wc -c </etc/passwd
et vous pouvez voir ce qu'il fait.
Les BSD (Mac OS X) stat
ont un indicateur d'argument de format différent et des spécificateurs de champ différents. De man stat(1)
:
-f format
: Affiche des informations en utilisant le format spécifié. Voir la section FORMATS pour une description des formats valides.z
: La taille du fichier en octets.Alors tous ensemble maintenant:
stat -f%z myfile1.txt
Cela dépend de ce que vous entendez par taille .
size=$(wc -c < "$file")
vous donnera le nombre d'octets pouvant être lus dans le fichier. IOW, c'est la taille du contenu du fichier. Cependant, le contenu du fichier sera lu (sauf s'il s'agit d'un fichier normal ou d'un lien symbolique vers un fichier normal dans la plupart des wc
implémentations, à titre d'optimisation). Cela peut avoir des effets secondaires. Par exemple, pour un canal nommé, ce qui a été lu ne peut plus être lu à nouveau et pour des choses comme /dev/zero
ou /dev/random
qui sont de taille infinie, cela va prendre un certain temps. Cela signifie également que vous avez besoin d'une read
autorisation pour le fichier et que le dernier horodatage d'accès au fichier peut être mis à jour.
C'est standard et portable, mais notez que certaines wc
implémentations peuvent inclure des blancs non significatifs dans cette sortie. Une façon de s'en débarrasser est d'utiliser:
size=$(($(wc -c < "$file")))
ou pour éviter une erreur sur une expression arithmétique vide dans dash
ou yash
quand wc
ne produit aucune sortie (comme lorsque le fichier ne peut pas être ouvert):
size=$(($(wc -c < "$file") +0))
ksh93
a wc
intégré (à condition de l'activer, vous pouvez également l'invoquer comme command /opt/ast/bin/wc
), ce qui en fait le moyen le plus efficace pour les fichiers normaux de ce shell.
Différents systèmes ont une commande appelée stat
interface permettant d’ appeler le stat()
ou les lstat()
appels système.
Ceux-ci rapportent des informations trouvées dans l'inode. L'une de ces informations est l' st_size
attribut. Pour les fichiers normaux, c'est la taille du contenu (combien de données pourraient être lues en l'absence d'erreur (c'est ce que la plupart des wc -c
implémentations utilisent dans leur optimisation)). Pour les liens symboliques, il s'agit de la taille en octets du chemin cible. Pour les canaux nommés, selon le système, il s'agit de 0 ou du nombre d'octets actuellement dans le tampon de canal. Idem pour les périphériques en mode bloc où, selon le système, vous obtenez 0 ou la taille en octets du stockage sous-jacent.
Vous n'avez pas besoin d'une autorisation de lecture sur le fichier pour obtenir ces informations, vous devez uniquement rechercher une autorisation d'accès au répertoire auquel il est lié.
Par ordre chronologique, il y a:
IRIXstat
(90's):
stat -qLs -- "$file"
renvoie l' st_size
attribut de $file
( lstat()
) ou:
stat -s -- "$file"
idem sauf lorsqu'il $file
s'agit d'un lien symbolique, auquel cas il s'agit st_size
du fichier après la résolution du lien symbolique.
zsh
stat
intégré (maintenant aussi appelé zstat
) dans le zsh/stat
module (chargé avec zmodload zsh/stat
) (1997):
stat -L +size -- $file # st_size of file
stat +size -- $file # after symlink resolution
ou pour stocker dans une variable:
stat -L -A size +size -- $file
évidemment, c'est le plus efficace dans cette coquille.
GNUstat
(2001); également dans BusyBox stat
depuis 2005 (copie de GNU stat
):
stat -c %s -- "$file" # st_size of file
stat -Lc %s -- "$file" # after symlink resolution
(notez que la signification de -L
est inversée par rapport à IRIX ou zsh
stat
.
BSDstat
(2002):
stat -f %z -- "$file" # st_size of file
stat -Lf %z -- "$file" # after symlink resolution
Ou vous pouvez utiliser la fonction stat()
/ lstat()
de certains langages de script tels que perl
:
perl -le 'print((lstat shift)[7])' -- "$file"
AIX propose également une istat
commande qui dumpe toutes les informations stat()
( lstat()
qui ne fonctionneront pas , cela ne fonctionnera pas sur les liens symboliques) et avec lesquelles vous pourriez post-traiter, par exemple:
LC_ALL=C istat "$file" | awk 'NR == 4 {print $5}'
(Merci @JeffSchaller pour l' aide à la définition des détails ).
Dans tcsh
:
@ size = -Z $file:q
(taille après résolution du lien symbolique)
Bien avant que GNU n'introduise sa stat
commande, la même chose pouvait être obtenue avec la find
commande GNU avec son -printf
prédicat (déjà en 1991):
find -- "$file" -prune -printf '%s\n' # st_size of file
find -L -- "$file" -prune -printf '%s\n' # after symlink resolution
Un problème cependant est que cela ne fonctionne pas si $file
commence avec -
ou est un find
prédicat (comme !
, (
...).
La commande standard pour obtenir les informations stat()
/ lstat()
est ls
.
POSIXly, vous pouvez faire:
LC_ALL=C ls -dn -- "$file" | awk '{print $5; exit}'
et ajouter -L
pour la même après la résolution de lien symbolique. Cela ne fonctionne pas pour les fichiers de périphérique où le 5ème champ est le numéro majeur de périphérique au lieu de la taille.
Pour les périphériques en mode bloc, les systèmes où la valeur stat()
0 est retournée st_size
ont généralement d'autres API pour indiquer la taille du périphérique en bloc. Par exemple, Linux a le BLKGETSIZE64
ioctl()
, et la plupart des distributions Linux sont maintenant livrées avec une blockdev
commande qui peut s’en servir:
blockdev --getsize64 -- "$device_file"
Cependant, vous avez besoin d'une autorisation de lecture sur le fichier de périphérique pour cela. Il est généralement possible de calculer la taille par d'autres moyens. Par exemple (toujours sous Linux):
lsblk -bdno size -- "$device_file"
Devrait fonctionner sauf pour les appareils vides.
Une approche qui fonctionne pour tous les fichiers pouvant être recherchés (inclut donc les fichiers normaux, la plupart des périphériques en mode bloc et certains périphériques avec des caractères) consiste à ouvrir le fichier et à rechercher jusqu'à la fin:
Avec zsh
(après chargement du zsh/system
module):
{sysseek -w end 0 && size=$((systell(0)))} < $file
Avec ksh93
:
< "$file" <#((size=EOF))
ou
{ size=$(<#((EOF))); } < "$file"
avec perl
:
perl -le 'seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN' < "$file"
Pour les pipes nommés, nous avons vu que certains systèmes (AIX, Solaris, HP / UX au moins) font la quantité de données dans le tampon de tube disponible dans stat()
« s st_size
. Certains (comme Linux ou FreeBSD) ne le font pas.
Sous Linux au moins, vous pouvez utiliser le FIONREAD
ioctl()
code après avoir ouvert le tuyau (en mode lecture + écriture pour éviter tout blocage):
fuser -s -- "$fifo_file" &&
perl -le 'require "sys/ioctl.ph";
ioctl(STDIN, &FIONREAD, $n) or die$!;
print unpack "L", $n' <> "$fifo_file"
Cependant, notez que bien que le contenu du tuyau ne soit pas lu , la simple ouverture du tuyau nommé ici peut toujours avoir des effets secondaires. Nous fuser
vérifions d’abord que certains processus sont déjà ouverts, mais ce n’est pas infaillible, car fuser
ils ne pourront peut-être pas vérifier tous les processus.
Jusqu'à présent, nous n'avons pris en compte que la taille des données primaires associées aux fichiers. Cela ne tient pas compte de la taille des métadonnées et de toute l'infrastructure requise pour stocker ce fichier.
Un autre attribut inode renvoyé par stat()
is st_blocks
. C'est le nombre de blocs de 512 octets utilisé pour stocker les données du fichier (et parfois certaines de ses métadonnées, comme les attributs étendus sur les systèmes de fichiers ext4 sous Linux). Cela n'inclut pas l'inode lui-même ni les entrées des répertoires auxquels le fichier est lié.
La taille et l'utilisation du disque ne sont pas nécessairement étroitement liées: compression, faible densité (parfois quelques métadonnées), une infrastructure supplémentaire telle que les blocs indirects dans certains systèmes de fichiers ont une influence sur ce dernier.
C'est généralement ce qui du
utilise pour signaler l'utilisation du disque. La plupart des commandes répertoriées ci-dessus pourront vous fournir cette information.
POSIXLY_CORRECT=1 ls -sd -- "$file" | awk '{print $1; exit}'
POSIXLY_CORRECT=1 du -s -- "$file"
(pas pour les répertoires où cela inclurait l'utilisation du disque des fichiers à l'intérieur).find -- "$file" -printf '%b\n'
zstat -L +block -- $file
stat -c %b -- "$file"
stat -f %b -- "$file"
perl -le 'print((lstat shift)[12])' -- "$file"
wc -c
utilise fstat
, mais lit ensuite les derniers st_blksize
octets. Apparemment, cela est dû au fait que les fichiers sous Linux /proc
et /sys
par exemple ont des tailles de statistiques approximatives . C'est bon pour l'exactitude, mais mauvais si la fin du fichier est sur le disque et non en mémoire (surtout si elle est utilisée sur plusieurs fichiers en boucle). Et très mauvais si le fichier est migré vers un stockage sur bande proche de la ligne , ou par exemple un système de fichiers FUSE à décompression transparente.
ls -go file | awk '{print $3}'
-go
seraient ceux de SysV, ils ne fonctionneraient pas sur les BSD (optionnel (XSI) dans POSIX). Vous aurez également besoin de ls -god file | awk '{print $3; exit}'
( -d
pour que cela fonctionne sur les répertoires, exit
pour les liens symboliques avec des lignes nouvelles dans la cible). Les problèmes avec les fichiers de périphérique demeurent également.
wc -c
indiquer le nombre d'octets.
Ce script combine plusieurs manières de calculer la taille du fichier:
(
du --apparent-size --block-size=1 "$file" 2>/dev/null ||
gdu --apparent-size --block-size=1 "$file" 2>/dev/null ||
find "$file" -printf "%s" 2>/dev/null ||
gfind "$file" -printf "%s" 2>/dev/null ||
stat --printf="%s" "$file" 2>/dev/null ||
stat -f%z "$file" 2>/dev/null ||
wc -c <"$file" 2>/dev/null
) | awk '{print $1}'
Le script fonctionne sur de nombreux systèmes Unix, notamment Linux, BSD, OSX, Solaris, SunOS, etc.
La taille du fichier indique le nombre d'octets. C'est la taille apparente, c'est-à-dire les octets que le fichier utilise sur un disque typique, sans compression spéciale, ni zones clairsemées spéciales, ni blocs non alloués, etc.
Ce script a une version de production avec plus d'aide et plus d'options ici: https://github.com/SixArm/file-size
stat semble le faire avec le moins d'appels système:
$ set debian-live-8.2.0-amd64-xfce-desktop.iso
$ strace stat --format %s $1 | wc
282 2795 27364
$ strace wc --bytes $1 | wc
307 3063 29091
$ strace du --bytes $1 | wc
437 4376 41955
$ strace find $1 -printf %s | wc
604 6061 64793
ls -l filename
vous donnera de nombreuses informations sur un fichier, y compris sa taille, ses autorisations et son propriétaire.
La taille du fichier dans la cinquième colonne et est affichée en octets. Dans l'exemple ci-dessous, la taille du fichier est juste en dessous de 2 Ko:
-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php
Edit: Ce n'est apparemment pas aussi fiable que la stat
commande.
ls -l
et stat
prescris donner des informations de taille fiable. Je n'ai trouvé aucune référence au contraire. ls -s
donnera la taille en nombre de blocs.
du filename
vous dira l'utilisation du disque en octets.
Je préfère du -h filename
, ce qui vous donne la taille dans un format lisible par l'homme.
du
imprimés taille en blocs de 1024 octets et non en un simple décompte d'octets.
du
donne une sortie en nombre d'unités de 512 octets. GNU du
utilise des kilo-octets à la place, sauf s’il est appelé avec POSIXLY_CORRECT
dans son environnement.
Créez de petites fonctions utilitaires dans vos scripts de shell auxquelles vous pouvez déléguer.
Exemple
#! /bin/sh -
# vim: set ft=sh
# size utility that works on GNU and BSD systems
size(){
case $(uname) in
(Darwin | *BSD*)
stat -Lf %z -- "$1";;
(*) stat -c %s -- "$1"
esac
}
for f do
printf '%s\n' "$f : $(gzip < "$f" | wc -c) bytes (versus $(size "$f") bytes)"
done
Basé sur les informations de @ Stéphane Chazelas 'answer.
gzip -v < file > /dev/null
pour vérifier la compressibilité d'un fichier.
case
déclaration. case
est la construction Bourne / POSIX pour faire la correspondance de modèle. [[...]]
ksh / bash / zsh est seulement (avec des variations).
J'ai trouvé un paquebot AWK 1 et il y avait un bug mais je l'ai corrigé. J'ai également ajouté dans PetaBytes après TeraBytes.
FILE_SIZE=234234 # FILESIZE IN BYTES
FILE_SIZE=$(echo "${FILE_SIZE}" | awk '{ split( "B KB MB GB TB PB" , v ); s=1; while( $1>1024 ){ $1/=1024; s++ } printf "%.2f %s", $1, v[s] }')
Étant donné que stat ne figure pas sur tous les systèmes, vous pouvez presque toujours utiliser la solution AWK. Exemple; le Raspberry Pi n'a pas de stat mais il a un awk .
Un autre moyen compatible POSIX serait d'utiliser awk
avec sa length()
fonction qui retourne la longueur, en caractères sur chaque ligne du fichier d'entrée, à l'exclusion des caractères de nouvelle ligne. Donc en faisant
awk '{ sum+=length } END { print sum+NR }' file
nous nous assurons que NR
soit ajouté à sum
, ce qui donne le nombre total de caractères et le nombre total de nouvelles lignes rencontrées dans le fichier. La length()
fonction in awk
prend un argument qui, par défaut, length($0)
correspond à la ligne entière courante.
printf 'a\nb' | awk '{ sum+=length } END { print sum+NR }'
doit imprimer 3 mais en imprimer 4.
J'aime l'option wc moi-même. Jumelé avec 'bc', vous pouvez obtenir des décimales dans autant d'endroits que vous le souhaitez.
Je cherchais à améliorer un script que j'avais créé avec la colonne "taille du fichier" d'une commande "ls -alh". Je ne voulais pas seulement des tailles de fichier entières, et deux décimales semblaient convenir, alors après avoir lu cette discussion, j'ai proposé le code ci-dessous.
Je suggère de rompre la ligne au point-virgule si vous l'incluez dans un script.
file=$1; string=$(wc -c $file); bite=${string% *}; okay=$(echo "scale=2; $bite/1024" | bc);friend=$(echo -e "$file $okay" "kb"); echo -e "$friend"
Mon script s'appelle gpfl , pour "obtenir la longueur du fichier image". Je l'utilise après avoir fait un mogrifier sur un fichier dans imagemagick, avant d'ouvrir ou de recharger une image dans une visionneuse jpeg GUI.
Je ne sais pas comment cela constitue une "réponse", car il emprunte beaucoup à ce qui a déjà été proposé et discuté. Donc je vais le laisser là.
BZT
wc
lit le dernier bloc du fichier, au cas où ce stat.st_size
ne serait qu'une approximation (comme pour Linux /proc
et les /sys
fichiers). Je suppose qu'ils ont décidé de ne pas faire le principal commentaire plus compliqué quand ils ont ajouté que la logique quelques lignes vers le bas: lingrok.org/xref/coreutils/src/wc.c#246
La méthode la plus rapide et la plus simple (IMO) est la suivante:
bash_var=$(stat -c %s /path/to/filename)
du
et des wc
réponses qui devraient avoir une mise en garde Ne jamais faire cela dans la vie réelle. Je viens d'utiliser ma réponse dans une application réelle ce soir et je pensais que cela valait la peine d'être partagé. Je suppose que nous avons tous nos opinions haussements d'épaules .