Como posso obter o tamanho de um arquivo em um script bash?

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

  • stackoverflow.com/questions/5920333/how-to-check-size-of-a-file LOL para migrar 🙂
  • Pareie com pv e cat para um comando de cópia que mostra o progresso e o ETA 🙂
  • stat -c% s file. nome
  • No caso de um problema XY (muito restrito), isso é legal: se tudo o que você precisa é testar se o arquivo tem um tamanho diferente de zero, bash tem uma expressão condicional -s, então você pode simplesmente testar se um arquivo tem comprimento diferente de zero com if [ -s file ]; then echo "file has nonzero size" ; fi

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 comparando stat --printf="%s" file.any | xxd - com stat -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 por du é 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, portanto size=$(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 usa fstat, 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 e wc deseja relatar o tamanho real, não o tamanho relatado por estatísticas. Eu acho que seria estranho para wc -c relatar um tamanho diferente de wc, 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 executar strace 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, é o st_size do arquivo após a resolução do link simbólico.

  • zsh stat integrado (agora também conhecido como zstat) no módulo zsh/stat (carregado com zmodload 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 BusyBox stat desde 2 005 (copiado do GNU stat):

    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 ou zsh 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ódulo zsh/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 usa fstat, 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 de ls -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 e stat 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. GNU du usa kibibytes, a menos que seja chamado com POSIXLY_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 e wc 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 .

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *