Como posso obter o tamanho de um arquivo em um script bash?
Como atribuo isso a uma variável bash para que possa usá-la mais tarde?
Comentários
Resposta
Sua melhor aposta se estiver em um sistema GNU:
stat --printf="%s" file.any
De man stat :
% s tamanho total, em bytes
Em um script bash:
#!/bin/bash FILENAME=/home/heiko/dummy/packages.txt FILESIZE=$(stat -c%s "$FILENAME") echo "Size of $FILENAME = $FILESIZE bytes."
NOTA: consulte
resposta de @chbrown ” sobre como usar estatísticas no terminal no Mac OS X.
Comentários
- @ haunted85
stat
é a maneira mais direta, assumindo que você ‘ está usando Linux ou Cygwin (stat
isn ‘ t padrão).wc -c
como sugerido por Eug é ne é portátil. -
stat: illegal option -- c
-
stat --printf="%s" file.txt
não ‘ t produza qualquer coisa no Debian Jessie … - No MacOS isso funciona:
stat -f%z myfile.tar
- @woohoo Seu prompt sobrescreve a saída.
man stat
diz que –printf omite a nova linha final. Use--format
ou-c
para ver a saída. Obtenha mais informações comparandostat --printf="%s" file.any | xxd -
comstat -c "%s" file.any | xxd -
Resposta
file_size_kb=`du -k "$filename" | cut -f1`
O problema de usar stat
é que é uma extensão GNU (Linux). du -k
e cut -f1
são especificados por POSIX e, portanto, são portáteis para qualquer sistema Unix.
Solaris, por exemplo, vem com bash, mas não com stat
. Portanto, isso não é totalmente hipotético.
ls
tem um problema semelhante em que o formato exato da saída não é especificado, portanto, a análise de sua saída não pode ser feita de forma portável . du -h
também é uma extensão GNU.
Atenha-se a construções portáteis sempre que possível, e você tornará a vida de alguém mais fácil no futuro. Talvez a sua.
Comentários
-
du
não ‘ dá o tamanho do arquivo, dá uma indicação de quanto espaço o arquivo usa, que é sutilmente diferente (geralmente o tamanho relatado pordu
é o tamanho do arquivo arredondado para o mais próximo número de blocos, onde um bloco é normalmente 512B ou 1kB ou 4kB). - @Gilles, arquivos esparsos (ou seja, aqueles com orifícios) relatam menos do que o comprimento.
- Esta, com
--bytes
ou-b
em vez de-k
, deve ser a resposta aceita. - @fralau: O OP deseja ” atribuir isso a uma variável bash para que possam usá-la posteriormente “, então é muito mais provável que eles queiram uma atuação um valor numérico, não uma aproximação legível por humanos. Além disso,
-h
é uma extensão GNU; não é padrão - Usar du com
--apparent-size
sinalizador retornará um mais tamanho preciso (conforme declarado no man:print apparent sizes, rather than disk usage; although the apparent size is usually smaller, it may be larger due to holes in ('sparse') files, internal fragmentation, indirect blocks, and the like
)
Resposta
Você também pode usar o comando” contagem de palavras “(wc
):
wc -c "$filename" | awk "{print $1}"
O problema com wc
é que ele “adiciona o nome do arquivo e indenta a saída. Por exemplo:
$ wc -c somefile.txt 1160 somefile.txt
Se você quiser evitar o encadeamento de uma linguagem interpretada completa ou editor de fluxo apenas para obter uma contagem do tamanho do arquivo, basta redirecionar a entrada do arquivo para que wc
nunca veja o nome do arquivo:
wc -c < "$filename"
Esta última forma pode ser usada com a substituição do comando para obter facilmente o valor que você estava procurando como uma variável de shell, conforme mencionado por Gilles abaixo.
size="$(wc -c <"$filename")"
Comentários
-
wc -c <"$FILENAME"
fornece o tamanho sem outro conteúdo, portantosize=$(wc -c <"$FILENAME")
- Só mais um ponto: acabei de testar e
wc -c < file
parece ser muito rápido, pelo menos no OS X. Eu ‘ estou supondo que wc tem cérebro para tentar stat o arquivo se apenas -c for especificado. - @EdwardFalk: GNU
wc -c
usafstat
, mas então procura o penúltimo bloco do arquivo e lê o último atést_blksize
bytes. Aparentemente isso ocorre porque os arquivos no Linux ‘ s/proc
e/sys
por exemplo, tem tamanhos de estatísticas que são apenas aproximados ewc
deseja relatar o tamanho real, não o tamanho relatado por estatísticas. Eu acho que seria estranho parawc -c
relatar um tamanho diferente dewc
, mas ‘ não é idéia de ler dados do arquivo se ‘ é um arquivo de disco normal e ‘ não está na memória. Ou pior, armazenamento de fita próximo à linha … - Parece que
printf
ainda vê a indentação, por exemplo,printf "Size: $size"
– >size: <4 spaces> 54339
. Por outro lado,echo
ignora o espaço em branco. Alguma maneira de torná-lo consistente? - @keithpjolley: chamando
fstat
Tente executarstrace wc -c </etc/passwd
e você poderá ver o que ele está fazendo.
Resposta
BSD “s (macOS” s) stat
tem um sinalizador de argumento de formato diferente e especificadores de campo diferentes. De man stat(1)
:
-
-f format
: exibe informações usando o formato especificado. Consulte a seção FORMATOS para obter uma descrição dos formatos válidos. - … a seção FORMATOS …
-
z
: O tamanho de arquivo em bytes.
Então, todos juntos agora:
stat -f%z myfile1.txt
NOTA: consulte @ b01 “s resposta sobre como usar o comando stat
em sistemas GNU / Linux. 🙂
Comentários
- Observe que esta é uma solução somente BSD. Ela não ‘ funciona com GNU
stat
, infelizmente.
Resposta
Depende do que você entende por tamanho .
size=$(wc -c < "$file")
fornecerá o número de bytes que podem ser lidos do arquivo. IOW, é o tamanho do conteúdo do arquivo. No entanto, ele lerá o conteúdo do arquivo (exceto se o arquivo for um arquivo regular ou um link simbólico para um arquivo regular na maioria das wc
implementações como uma otimização). Isso pode ter efeitos colaterais. Por exemplo, para um pipe nomeado, o que foi lido não pode mais ser lido novamente e para coisas como /dev/zero
ou /dev/random
que são de tamanho infinito, vai demorar um pouco. Isso também significa que você precisa da read
permissão para o arquivo, e o carimbo de data / hora do último acesso do arquivo pode ser atualizado.
Isso é padrão e portátil, no entanto, observe que algumas implementações de wc
podem incluir espaços em branco à esquerda nessa saída. Uma maneira de se livrar deles é usar:
size=$(($(wc -c < "$file")))
ou evitar um erro sobre uma expressão aritmética vazia em dash
ou yash
quando wc
não produz saída (como quando o arquivo não pode “ser aberto):
size=$(($(wc -c < "$file") +0))
ksh93
tem wc
integrado (desde que habilite, você também pode invocá-lo como command /opt/ast/bin/wc
), o que o torna mais eficiente para arquivos regulares nesse shell.
Vários sistemas têm um comando chamado stat
essa é uma interface para as chamadas de sistema stat()
ou lstat()
.
Essas informações de relatório encontradas nas inode. Uma dessas informações é o atributo st_size
. Para arquivos regulares, esse é o tamanho do conteúdo (quantos dados poderiam ser lidos na ausência de erro (isso é o que a maioria das wc -c
implementações usa em sua otimização) ) Para links simbólicos, esse é o tamanho em bytes do caminho de destino. Para canais nomeados, dependendo do sistema, é 0 ou o número de bytes atualmente no buffer de canal. O mesmo para dispositivos de bloco onde, dependendo do sistema, você obtém 0 ou o tamanho em bytes do armazenamento subjacente.
Você não precisa de permissão de leitura para o arquivo para obter essa informação, apenas a permissão de pesquisa para o diretório ao qual está vinculado.
Por ordem cronológica, existe:
-
IRIX
stat
(90 “s):stat -qLs -- "$file"
retorna o
st_size
atributo de$file
(lstat()
) ou:stat -s -- "$file"
mesmo, exceto quando
$file
é um link simbólico, nesse caso, é ost_size
do arquivo após a resolução do link simbólico. -
zsh
stat
integrado (agora também conhecido comozstat
) no módulozsh/stat
(carregado comzmodload zsh/stat
) (1997):stat -L +size -- $file # st_size of file stat +size -- $file # after symlink resolution
ou para armazenar em uma variável:
stat -L -A size +size -- $file
obviamente, esse é o mais eficiente em esse shell.
-
GNU
stat
(2001); também no BusyBoxstat
desde 2 005 (copiado do GNUstat
):stat -c %s -- "$file" # st_size of file stat -Lc %s -- "$file" # after symlink resolution
(observe o significado de
-L
é invertido em comparação com IRIX ouzsh
stat
. -
BSDs
stat
(2002):stat -f %z -- "$file" # st_size of file stat -Lf %z -- "$file" # after symlink resolution
Ou você pode usar a função stat()
/ lstat()
de alguma linguagem de script como perl
:
perl -le "print((lstat shift)[7])" -- "$file"
O AIX também tem um istat
comando que irá descartar todos os stat()
(não lstat()
, então não funcionará em links simbólicos ) informações e com as quais você pode pós-processar, por exemplo:
LC_ALL=C istat "$file" | awk "NR == 4 {print $5}"
(obrigado @JeffSchaller pelo ajuda a descobrir os detalhes ).
Em tcsh
:
@ size = -Z $file:q
(tamanho após a resolução do link simbólico)
Muito antes do GNU introduzir seu comando stat
, o mesmo poderia ser alcançado com o GNU find
comando com seu -printf
predicado (já em 1991):
find -- "$file" -prune -printf "%s\n" # st_size of file find -L -- "$file" -prune -printf "%s\n" # after symlink resolution
Um problema, porém, é que não funcione se $file
começar com -
ou for um find
predicado (como !
, (
…).
O comando padrão para obter o stat()
/ lstat()
as informações são ls
.
POSIXly, você pode fazer:
LC_ALL=C ls -dn -- "$file" | awk "{print $5; exit}"
e adicione -L
para o mesmo após a resolução do link simbólico. Isso não funciona para arquivos de dispositivo, embora o campo 5 th seja o número principal do dispositivo em vez do tamanho.
Para dispositivos de bloco, sistemas onde stat()
retorna 0 para st_size
, geralmente tem outras APIs para relatar o tamanho do dispositivo de bloco. Por exemplo, o Linux tem o BLKGETSIZE64
ioctl()
, e a maioria das distribuições Linux agora vêm com um comando blockdev
que pode fazer uso dele:
blockdev --getsize64 -- "$device_file"
No entanto, você precisa de permissão de leitura para o arquivo do dispositivo para isso. Geralmente é possível derivar o tamanho por outros meios. Por exemplo (ainda no Linux):
lsblk -bdno size -- "$device_file"
Deve funcionar, exceto para dispositivos vazios.
Uma abordagem que funciona para todos arquivos buscáveis (o que inclui arquivos regulares, a maioria dos dispositivos de bloco e alguns dispositivos de caracteres) é abrir o arquivo e buscar até o fim:
-
Com
zsh
(depois de carregar o módulozsh/system
):{sysseek -w end 0 && size=$((systell(0)))} < $file
-
Com
ksh93
:< "$file" <#((size=EOF))
ou
{ size=$(<#((EOF))); } < "$file"
-
com
perl
:perl -le "seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN" < "$file"
Para canais nomeados, vimos que alguns sistemas (AIX, Solaris, HP / UX, pelo menos) disponibilizam a quantidade de dados no buffer de canal em stat()
“s st_size
. Alguns (como Linux ou FreeBSD) não.
Pelo menos no Linux, você pode usar o FIONREAD
ioctl()
depois de abrir o pipe (no modo de leitura + gravação para evitar que ele trave):
fuser -s -- "$fifo_file" && perl -le "require "sys/ioctl.ph"; ioctl(STDIN, &FIONREAD, $n) or die$!; print unpack "L", $n" <> "$fifo_file"
No entanto, observe que embora ele não “ leia o conteúdo do tubo, a mera abertura do tubo nomeado aqui ainda pode ter efeitos colaterais. Estamos usando fuser
para verificar primeiro se algum processo já tem o tubo aberto para aliviar isso, mas isso não é infalível como fuser
pode não ser capaz de verificar todos os processos.
Agora, até agora, consideramos apenas o tamanho dos dados primários associados aos arquivos.Isso não leva em consideração o tamanho dos metadados e toda a infraestrutura de suporte necessária para armazenar esse arquivo.
Outro atributo inode retornado por stat()
é st_blocks
. Esse é o número de blocos de 512 bytes que é usado para armazenar os dados do arquivo (e às vezes alguns de seus metadados, como os atributos estendidos em sistemas de arquivos ext4 no Linux). “t inclua o próprio inode ou as entradas nos diretórios aos quais o arquivo está vinculado.
O tamanho e o uso do disco não estão necessariamente relacionados como compactação, dispersão (às vezes alguns metadados), infraestrutura extra como blocos indiretos em alguns sistemas de arquivos têm influência sobre o último.
Isso é tipicamente o que du
usa para relatar o uso do disco. A maioria dos comandos listados acima serão capazes de obter essas informações.
-
POSIXLY_CORRECT=1 ls -sd -- "$file" | awk "{print $1; exit}"
-
POSIXLY_CORRECT=1 du -s -- "$file"
(não para diretórios onde isso incluiria o usag de disco e dos arquivos dentro). - GNU
find -- "$file" -printf "%b\n"
-
zstat -L +block -- $file
- GNU
stat -c %b -- "$file"
- BSD
stat -f %b -- "$file"
-
perl -le "print((lstat shift)[12])" -- "$file"
Comentários
- claramente a resposta mais abrangente e informativa. obrigada. posso usar isso para criar scripts bash de plataforma cruzada usando as informações de estatísticas BSD e GNU
- Curiosidade: GNU coreutils
wc -c
usafstat
, mas então lê os últimos atést_blksize
bytes. Aparentemente isso ocorre porque os arquivos no Linux ‘ s/proc
e/sys
por exemplo, têm tamanhos de estatísticas que são apenas aproximados . Isso é bom para a correção, mas ruim se o final do arquivo estiver no disco e não na memória (especialmente se usado em muitos arquivos em um loop). E muito ruim se o arquivo for migrado para armazenamento em fita near-line ou, por exemplo, um sistema de arquivos FUSE de descompressão transparente. - isso também não funcionaria
ls -go file | awk '{print $3}'
- @StevenPenny aqueles
-go
seriam os SysV, eles não ‘ funcionariam em BSDs (opcional (XSI) em POSIX). Você ‘ d também precisa dels -god file | awk '{print $3; exit}'
(-d
para que funcione em diretórios,exit
para links simbólicos com novas linhas no destino). Os problemas com arquivos de dispositivo também permanecem. - @ αғsнιη a API do Unix não faz distinção entre arquivos de texto e binários. É ‘ todas as sequências de bytes. Alguns aplicativos podem querer interpretar esses bytes como texto, mas obviamente não
wc -c
que informa o número de bytes.
Resposta
Este script combina várias maneiras de calcular o tamanho do arquivo:
( 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}"
O script funciona em muitos sistemas Unix incluindo Linux, BSD, OSX, Solaris, SunOS, etc.
O tamanho do arquivo mostra o número de bytes. É o tamanho aparente, que são os bytes que o arquivo usa em um disco típico, sem compressão especial, ou áreas esparsas especiais, ou blocos não alocados, etc.
Este script tem uma versão de produção com mais ajuda e mais opções aqui: https://github.com/SixArm/file-size
Resposta
stat parece fazer isso com o menor número de chamadas do sistema:
$ 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
Resposta
ls -l filename
fornecerá muitas informações sobre um arquivo, incluindo seu tamanho, permissões e proprietário.
O tamanho do arquivo na quinta coluna e é exibido em bytes. No exemplo abaixo, o tamanho do arquivo está abaixo de 2 KB:
-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php
Editar: Aparentemente, não é tão confiável quanto o comando stat
.
Comentários
- Acho que os comandos
ls -l
estat
fornecem informações confiáveis sobre o tamanho. Não encontrei nenhuma referência ao contrário.ls -s
dará o tamanho em número de blocos. - @ dabest1 it ‘ não é confiável no sentido de que em outro unix, sua saída pode ser diferente (e em alguns unix é).
- Sim, IIRC, Solaris não ‘ exibiu o nome do grupo por padrão, levando a menos colunas na saída.
- Como o tamanho é numérico puro, cercado por espaços em branco, e o ano da data é numérico puro, em um formato definido, seria possível usar um regexp para tratar o usuário + proprietário como um campo, estando o grupo ou não presente. (um exercício para o leitor!)
Resposta
du filename
lhe dirá o uso do disco em bytes.
Eu prefiro du -h filename
, que fornece o tamanho em um formato legível por humanos.
Comentários
- que ou
stat -c "%s"
😉 - Este tipo de
du
imprime o tamanho em blocos de 1.024 bytes, não uma simples contagem de bytes. - Observe que o
du
padrão fornece uma saída em unidades de 512 bytes. GNUdu
usa kibibytes, a menos que seja chamado comPOSIXLY_CORRECT
em seu ambiente. - Para arquivos do tipo diretório , que fornece o uso do disco do diretório, mas também de todos os outros arquivos dentro (recursivamente).
Resposta
Crie pequenas funções de utilitário em seus scripts de shell que você pode delegar.
Exemplo
#! /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
Com base nas informações da resposta de @ Stéphane Chazelas “.
Comentários
- Veja também
gzip -v < file > /dev/null
para verificar a compressibilidade de um arquivo. - @St é phaneChazelas não tenho certeza se acho que foi uma melhoria. essas declarações de caso podem facilmente desanimar; certamente nunca me lembro de como corrigi-las 🙂 são declarações de caso inerentemente mais portáteis, já que você entendi? vejo o ponto quando há mais de dois casos, mas fora isso … +
- Suponho que ‘ também seja uma questão de gosto, mas aqui é ‘ é o caso típico em que você ‘ d deseja usar um
case
declaração.case
é a construção Bourne / POSIX para fazer correspondência de padrões.[[...]]
é ksh / bash / zsh apenas (com variações).
Resposta
Eu encontrei um liner AWK 1, e tinha um bug, mas eu consertei. Eu também adicionei PetaBytes apó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] }")
Considerando stat não está em todos os sistemas, quase sempre você pode usar a solução AWK. Exemplo; o Raspberry Pi não tem stat , mas tem awk .
Comentários
- NÃO é o que o OP pediu, mas um belo trabalho.
Resposta
Eu mesmo gosto da opção wc. Emparelhado com “bc”, você pode obter decimais para quantos lugares quiser.
Eu estava procurando melhorar um script que fiz que editei a coluna “tamanho do arquivo” de um “ls – alh “comando. Eu não queria apenas tamanhos de arquivo inteiros e dois decimais pareciam se adequar, então, depois de ler esta discussão, eu vim com o código abaixo.
Eu sugiro quebrar a linha nos pontos-e-vírgulas se você incluir isso em um 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"
Meu script é denominado gpfl , para “obter comprimento do arquivo de imagem.” Eu o uso depois de fazer um mogrify em um arquivo no imagemagick, antes de abrir ou recarregar uma imagem em um visualizador jpeg da GUI.
Não sei como isso se classifica como uma “resposta”, pois toma emprestado muito do que já foi oferecido e discutido. Então, vou deixar isso aí.
BZT
Comentários
- Eu prefiro usar ” stat ” ou ” ls “. Normalmente eu não ‘ t gosto de usar ” wc ” para obter tamanhos de arquivo porque ele lê fisicamente o arquivo inteiro. Se você tiver muitos arquivos, ou arquivos particularmente grandes, isso pode levar muito tempo. Mas sua solução é criativa … + 1.
- Concordo com a ideia de usar ” stat ” sobre ” wc ” para o tamanho do arquivo, no entanto, se você usar ” wc -c “, nenhum dado será lido; em vez disso, lseek será usado para descobrir o número de bytes em um arquivo. lingrok.org/xref/coreutils/src/wc.c#228
- @ bbaja42 : observe que GNU Coreutils lê o último bloco do arquivo, no caso de
stat.st_size
ser apenas uma aproximação (como para Linux/proc
e/sys
arquivos). Acho que eles decidiram não complicar o comentário principal ao adicionar essa lógica algumas linhas abaixo: lingrok.org/xref/coreutils/src/wc.c#246
Resposta
O método mais rápido e simples (IMO) é:
bash_var=$(stat -c %s /path/to/filename)
Comentários
- Em seguida, vote positivamente em uma ou mais das respostas existentes que mencionam stat; não há necessidade de repetir novamente …
- @JeffSchaller Acabei de votar a resposta de Stephane ‘ em suas instruções.Acho que é muito complicado para meus propósitos. É por isso que postei esta resposta simples para almas com pensamentos semelhantes.
- Obrigado; ele ‘ é apenas uma sexta instância de um ” stat ” resposta não ‘ t simplifica este Q & A, mas prefere fazer um novo leitor se perguntar ” como esta resposta difere das outras? ” e leva a mais confusão em vez de menos.
- @JeffSchaller, eu acho. Mas eu poderia reclamar das muitas respostas
du
ewc
que deveriam ter uma isenção de responsabilidade NUNCA FAÇA ISSO na vida real vida. Acabei de usar minha resposta em um aplicativo da vida real esta noite e achei que valia a pena compartilhar. Acho que todos nós temos nossas opiniões encolhe os ombros .
pv
ecat
para um comando de cópia que mostra o progresso e o ETA 🙂-s
, então você pode simplesmente testar se um arquivo tem comprimento diferente de zero comif [ -s file ]; then echo "file has nonzero size" ; fi