Sous Linux, j'utilise stat --format="%s" FILE
, mais Solaris auquel j'ai accès n'a pas de commande stat. Que dois-je utiliser alors?
J'écris des scripts Bash et je ne peux pas vraiment installer de nouveau logiciel sur le système.
J'ai déjà envisagé d'utiliser:
perl -e '@x=stat(shift);print $x[7]' FILE
ou même:
ls -nl FILE | awk '{print $5}'
Mais ni l'un ni l'autre ne semble raisonnable - exécuter Perl juste pour obtenir la taille du fichier? Ou exécuter 2 commandes pour faire la même chose?
Réponses:
wc -c < filename
(abréviation de word count,-c
imprime le nombre d'octets) est une solution POSIX portable . Seul le format de sortie peut ne pas être uniforme sur toutes les plates-formes car certains espaces peuvent être ajoutés au début (ce qui est le cas pour Solaris).N'omettez pas la redirection d'entrée. Lorsque le fichier est passé en argument, le nom du fichier est imprimé après le nombre d'octets.
J'avais peur que cela ne fonctionne pas pour les fichiers binaires, mais cela fonctionne bien sur Linux et Solaris. Vous pouvez l'essayer avec
wc -c < /usr/bin/wc
. De plus, les utilitaires POSIX sont garantis pour gérer les fichiers binaires , sauf indication contraire explicite.la source
wc -c < file
si vous ne voulez pas que le nom du fichier apparaisse.wc
dans un pipeline,read()
le flux entier doit compter les octets. Lesls
/awk
solutions (et similaires) utilisent un appel système pour obtenir la taille, qui devrait être le temps linéaire (par rapport à O (taille))wc
avoir été très lent la dernière fois que j'ai fait ça sur un disque dur plein. C'était assez lent pour que je puisse réécrire le script avant que le premier ne soit terminé, je suis venu ici pour me rappeler comment je l'ai fait lol.wc -c
; il a l'air beaucoup plus soigné maisls
+awk
est meilleur pour l'utilisation de la vitesse / des ressources. De plus, je voulais juste souligner que vous devez également post-traiter les résultats,wc
car sur certains systèmes, il y aura des espaces avant le résultat, que vous devrez peut-être supprimer avant de pouvoir faire des comparaisons.wc -c
c'est génial, mais cela ne fonctionnera pas si vous n'avez pas d'accès en lecture au fichier.J'ai fini par écrire mon propre programme (vraiment petit) pour n'afficher que la taille. Plus d'informations ici: http://fwhacking.blogspot.com/2011/03/bfsize-print-file-size-in-bytes-and.html
Les deux moyens les plus propres à mon avis avec les outils Linux courants sont:
Mais je ne veux tout simplement pas taper des paramètres ou diriger la sortie uniquement pour obtenir une taille de fichier, donc j'utilise ma propre taille bfs.
la source
stat
est une option pour eux.wc -c
prend 4090 msec sur un fichier de 10 Mo contre "0" msec pourstat -c %s
, donc je conviens qu'il est utile d'avoir des solutions alternatives même si elles ne répondent pas exactement à la question posée.stat -c %s /usr/bin/stat
stat: illegal option -- c
usage: stat [-FlLnqrsx] [-f format] [-t timefmt] [file ...]
Même s'il
du
imprime généralement l'utilisation du disque et non la taille réelle des données, GNU coreutilsdu
peut imprimer la "taille apparente" du fichier en octets:Mais cela ne fonctionnera pas sous BSD, Solaris, macOS, ...
la source
brew install coreutils
etgdu -b
obtiendra le même effetwc
besoin de lire tout le fichier avant de donner un résultatdu
est immédiat.du -b
dans un tout autre contexte dedu
justification .lstat
appel, donc ses performances ne dépendent pas de la taille du fichier. Plus court questat -c '%s'
, mais moins intuitif et fonctionne différemment pour les dossiers (imprime la taille de chaque fichier à l'intérieur).du
peut se rapprocher en utilisantdu -A -B1
, mais il imprime toujours le résultat en multiples de blocs de 1024B. N'a pas réussi à le faire imprimer le nombre d'octets. Même la configurationBLOCKSIZE=1
dans l'environnement n'aide pas, car le bloc 512B est alors utilisé.Enfin, j'ai décidé d'utiliser ls et l'extension de tableau bash:
ce n'est pas vraiment sympa, mais au moins il ne fait qu'un fork + execve, et il ne repose pas sur un langage de programmation secondaire (perl / ruby / python / peu importe)
la source
ls -ln FILE | { read _ _ _ _ size _ && echo "$size"; }
n'a pas besoin de fork pour la deuxième étape du pipeline, car il n'utilise que des composants intégrés, mais Bash 4.2.37 sur Linux forks deux fois (toujours un seulexecve
, cependant).read _ _ _ _ size _ <<<"$(exec ls -ln /usr/bin/wc)" && echo "$size"
fonctionne avec un seul fork et un seul exec, mais il utilise un fichier temporaire pour la chaîne here-string. Il peut être rendu portable en remplaçant la chaîne here-string par here-document compatible POSX . BTW notez leexec
dans le sous-shell. Sans cela, Bash effectue un fork pour le sous-shell et un autre pour la commande exécutée à l'intérieur. C'est le cas dans le code que vous fournissez dans cette réponse. aussi.-l
est superflu en présence de-n
. Citant lals
page de manuel POSIX :: activez-n
l'-l
option (ell), mais lors de l'écriture du propriétaire ou du groupe du fichier, écrivez respectivement l'UID ou le GID numérique du fichier plutôt que le nom de l'utilisateur ou du groupe. Désactivez les-C
,-m
et les-x
options.Solution la plus rapide multiplateforme (utilise uniquement un seul fork () pour ls , n'essaie pas de compter les caractères réels, ne génère pas de awk, perl, etc. inutiles).
Testé sur MacOS, Linux - peut nécessiter des modifications mineures pour Solaris:
Si nécessaire, simplifiez les arguments ls et ajustez le décalage dans $ {__ ln [3]}.
Remarque: suivra les liens symboliques.
la source
Les BSD ont
stat
des options différentes de celles de GNU coreutils, mais des capacités similaires.Cela fonctionne sur macOS (testé sur 10.12), FreeBSD , NetBSD et OpenBSD .
la source
stat
Cependant, Solaris n'a pas du tout d' utilité.Lors du traitement de la
ls -n
sortie, comme alternative aux tableaux de shell mal portables, vous pouvez utiliser les arguments de position, qui forment le seul tableau et sont les seules variables locales du shell standard. Enveloppez l'écrasement des arguments de position dans une fonction pour conserver les arguments d'origine de votre script ou fonction.Cela divise la sortie de en
ln -dn
fonctionIFS
des paramètres actuels de la variable d'environnement, l'assigne aux arguments de position et fait écho au cinquième. Le-d
garantit que les répertoires sont gérés correctement et-n
garantit que les noms d'utilisateurs et de groupes n'ont pas besoin d'être résolus, contrairement à-l
. En outre, les noms d'utilisateurs et de groupes contenant des espaces peuvent théoriquement casser la structure de ligne attendue; ils sont généralement interdits, mais cette possibilité incite toujours le programmeur à réfléchir.la source
Si vous utilisez
find
des fileutils GNU:Malheureusement, d'autres implémentations de
find
ne prennent généralement pas en charge-maxdepth
, ni-printf
. C'est le cas, par exemple, de Solaris et de macOSfind
.la source
size=$(test -f filename && find filename -printf '%s')
.-maxdepth
est destiné à éviterfind
d'être récursif (puisque cestat
que l'OP doit remplacer ne l'est pas). Ilfind
manque un a à votre commande-name
et latest
commande n'est pas nécessaire.find
recherche ses paramètres de manière récursive pour les fichiers correspondant à des critères donnés. Si les paramètres ne sont pas des répertoires, la récursivité est… assez simple. Par conséquent, je teste d'abord qu'ilfilename
s'agit vraiment d'un fichier ordinaire existant, puis j'imprime sa taille en utilisantfind
qui n'a nulle part où récurer.find . -maxdepth 1 -type f -name filename -printf '%s'
ne fonctionne que si le fichier est dans le répertoire en cours, et il peut toujours examiner chaque fichier dans le répertoire, ce qui peut être lent. Meilleure utilisation (encore plus courte!)find filename -maxdepth 1 -type f -printf '%s'
.Vous pouvez utiliser la
find
commande pour obtenir un ensemble de fichiers (ici les fichiers temporaires sont extraits). Ensuite, vous pouvez utiliser ladu
commande pour obtenir la taille du fichier de chaque fichier sous une forme lisible par l'homme à l'aide de-h
commutateur.PRODUCTION:
la source
Votre premier exemple de Perl ne me paraît pas déraisonnable.
C'est pour des raisons comme celle-ci que j'ai migré de l'écriture de scripts shell (dans bash / sh etc.) à l'écriture de tous les scripts sauf les plus triviaux en Perl. J'ai trouvé que je devais lancer Perl pour des besoins particuliers, et comme je le faisais de plus en plus, je me suis rendu compte qu'écrire les scripts en Perl était probablement plus puissant (en termes de langage et du large éventail de bibliothèques disponibles via CPAN ) et un moyen plus efficace d'atteindre ce que je voulais.
Notez que d'autres langages de script shell (par exemple python / ruby) auront sans aucun doute des fonctionnalités similaires, et vous voudrez peut-être les évaluer pour vos besoins. Je ne parle que de Perl car c'est le langage que j'utilise et que je connais bien.
la source
si vous avez Perl sur votre Solaris, utilisez-le. Sinon, ls avec awk est votre prochain meilleur pari, puisque vous n'avez pas de statistiques ou que votre trouvaille n'est pas une trouvaille GNU.
la source
Il y a une astuce dans Solaris que j'ai utilisée, si vous demandez la taille de plus d'un fichier, il ne renvoie que la taille totale sans nom - incluez donc un fichier vide comme / dev / null comme deuxième fichier:
par exemple, fichier de commande que vous voulez / dev / null
Je ne peux pas me rappeler quelle commande de taille cela fonctionne pour ls / wc / etc - malheureusement, je n'ai pas de boîtier solaris pour le tester.
la source
sur Linux, vous pouvez utiliser
du -h $FILE
, cela fonctionne-t-il aussi sur Solaris?la source
Avez-vous essayé du -ks | awk '{print $ 1 * 1024}'. Cela pourrait bien fonctionner.
la source