Como verificar o tamanho de um arquivo usando o Bash?


145

Eu tenho um script que verifica o tamanho 0, mas achei que deveria haver uma maneira mais fácil de verificar o tamanho dos arquivos. Ou seja, file.txté normalmente 100k; como fazer um script verificar se é menor que 90k (incluindo 0) e fazer uma nova cópia porque o arquivo está corrompido nesse caso.

O que estou usando atualmente ..

if [ -n file.txt ]
then
 echo "everything is good"
else
 mail -s "file.txt size is zero, please fix. " myemail@gmail.com < /dev/null
 # Grab wget as a fallback 
 wget -c https://www.server.org/file.txt -P /root/tmp --output-document=/root/tmp/file.txt
 mv -f /root/tmp/file.txt /var/www/file.txt
fi

Respostas:


250

[ -n file.txt ]não verifica seu tamanho, verifica se a sequência file.txttem um comprimento diferente de zero e, portanto, sempre será bem-sucedida.

Se você quiser dizer "o tamanho é diferente de zero", é necessário [ -s file.txt ].

Para obter o tamanho de um arquivo, você pode usá wc -c-lo para obter o tamanho (tamanho do arquivo) em bytes:

file=file.txt
minimumsize=90000
actualsize=$(wc -c <"$file")
if [ $actualsize -ge $minimumsize ]; then
    echo size is over $minimumsize bytes
else
    echo size is under $minimumsize bytes
fi

Nesse caso, parece que é isso que você deseja.

Mas, para sua informação, se você quiser saber quanto espaço em disco o arquivo está usando, poderá du -kobter o tamanho (espaço em disco usado) em kilobytes:

file=file.txt
minimumsize=90
actualsize=$(du -k "$file" | cut -f 1)
if [ $actualsize -ge $minimumsize ]; then
    echo size is over $minimumsize kilobytes
else
    echo size is under $minimumsize kilobytes
fi

Se você precisar de mais controle sobre o formato de saída, também poderá ver stat. No Linux, você começaria com algo como stat -c '%s' file.txt, e no BSD / Mac OS X, algo como stat -f '%z' file.txt.


5
Por que ao du -b "$file" | cut -f 1invés de stat -c '%s' "$file"? Ou stat --printf="%s" "$file"?
— mivk

1
Só porque é mais portátil. BSD e Linux stat têm sinalizadores diferentes.
— Mikel

1
Eu tive que modificá-lo ... | cut -d' ' -f1para fazê-lo funcionar no Ubuntu.
— Mikepote

8
Use wc -c < "$file"(observe o <), caso em que você não precisa da | cut ...peça (que, conforme publicada, não funciona no OSX). O BLOCKSIZEvalor mínimo para duno OSX é 512.
— mklement0

3
@PetriSirkkala No meu sistema Linux, wc -c <filenametambém usa fstate seek? Observe que fstatleva um fd, não um nome de caminho.
— 26417 Mikel

24

Surpreende-me que ninguém tenha mencionado stato tamanho do arquivo. Alguns métodos são definitivamente melhores: usar -spara descobrir se o arquivo está vazio ou não é mais fácil do que qualquer outra coisa, se é tudo o que você deseja. E se você deseja encontrar arquivos de um tamanho, findcertamente é o caminho a percorrer.

Também gosto dumuito de obter o tamanho do arquivo em kb, mas, para bytes, eu usaria stat:

size=$(stat -f%z $filename) # BSD stat

size=$(stat -c%s $filename) # GNU stat?

2
staté uma ótima idéia, mas no CentOS foi isso que funcionou para mim: #size=$(stat -c%s $filename)
— Oz Solomon

2
A diferença entre GNU e BSD é o que, infelizmente, torna essa alternativa um pouco menos atraente. :(
— lapo 29/10

1
stat pode ser enganoso se o arquivo for escasso. Você pode usar os blocos relatados pelo stat para calcular o espaço usado.
— Ajith Antony

@AjithAntony Esse é um ponto interessante que não me ocorreu. Eu posso ver stata coisa certa em algumas situações, e arquivos esparsos não são relevantes na maioria das situações, embora certamente não todos.
— Daniel C. Sobral

17

solução alternativa com awk e parêntese duplo:

FILENAME=file.txt
SIZE=$(du -sb $FILENAME | awk '{ print $1 }')

if ((SIZE<90000)) ; then 
    echo "less"; 
else 
    echo "not less"; 
fi

1
Bom, mas não funciona no OSX, onde dunão suporta -b. (Pode ser uma escolha de estilo consciente, mas apenas para mencionar a alternativa: você pode omitir o $interior prefixo (( ... ))ao fazer referência a variáveis: ((SIZE<90000)))
— mklement0

1
Na verdade, foi uma edição de um usuário anterior que pensou que era errado para omitir a$
— fstab

2
@fstab, você pode omitir awkusando read( bashcomando interno):read SIZE _ <<<$(du -sb "$FILENAME")
— Jdamian

13

Se você findlida com essa sintaxe, você pode usá-la:

find -maxdepth 1 -name "file.txt" -size -90k

Isso resultará file.txtem stdout se e somente se o tamanho de file.txtfor menor que 90k. Para executar um script scriptse file.txttiver um tamanho menor que 90k:

find -maxdepth 1 -name "file.txt" -size -90k -exec script \;

3
+1, mas também para fazê-lo funcionar no OSX, você precisa de um argumento diretório de destino explícito, por exemplo:find . -maxdepth 1 -name "file.txt" -size -90k
— mklement0

8

Se você está procurando apenas o tamanho de um arquivo:

$ cat $file | wc -c
> 203233

1
Essa pode ser a resposta mais curta e viável, mas provavelmente também é a mais lenta. :)
— SunSparc 25/08

2
Sim, mas certamente economicamente superior: Custo do tempo de engenharia> Custo do tempo de computação
— BananaNeil

8
wc -c "$file"foi dada como resposta em 2011 (três anos atrás). Sim, wc -c "$file"tem o problema de exibir o nome do arquivo e a contagem de caracteres; portanto, as respostas anteriores adicionaram um comando para separar a contagem. Mas wc -c < "$file", que corrige esse problema, foi adicionado como comentário em maio de 2014. Sua resposta é equivalente a isso, exceto que ela adiciona um "uso inútil de cat" . Além disso, você deve citar todas as referências de variáveis ​​do shell, a menos que tenha um bom motivo para não fazê-lo.
— G-Man diz 'Reinstate Monica'

1
Você pode tornar isso mais eficiente usando head -c em vez de cat.if [$ (head -c 90000 $ arquivo | wc -c) -lt 90000]; em seguida, ecoa "O arquivo é menor que 90k"; fi. Testado no CentOS, ele pode ou não funcionar no BSD ou OSX.
— 22617 Kevin Keane

@BananaNeil como fazer esse processo a cada 20 segundos para que eu possa verificar o aumento do tamanho do arquivo etc.
— A Sahra 27/03

6

Isso funciona tanto em linux quanto em macos

function filesize
{
    local file=$1
    size=`stat -c%s $file 2>/dev/null` # linux
    if [ $? -eq 0 ]
    then
        echo $size
        return 0
    fi

    eval $(stat -s $file) # macos
    if [ $? -eq 0 ]
    then
        echo $st_size
        return 0
    fi

    return -1
}

5

O 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

Se eu entendi corretamente, o teste deve ser feito com também o redirecionamento de tubulação ?: strace du --bytes $1 2>&1 >/dev/null | wc Se for esse o caso, então em amd64 arquitetura no ArchLinux (versões mais recentes geralmente de tudo) Eu tenho 45 linhas para du, 46 linhas para stat, 47 linhas para wce 72 linhas para find.
— VasiliNovikov

5
python -c 'import os; print (os.path.getsize("... filename ..."))'

portátil, todos os tipos de python, evita variação nos dialetos estatísticos


4

Para obter o tamanho do arquivo no Linux e no Mac OS X (e provavelmente em outros BSDs), não há muitas opções, e a maioria das sugeridas aqui funcionará apenas em um sistema.

Dado f=/path/to/your/file,

o que funciona no Linux e no Mac 's Bash:

size=$( perl -e 'print -s shift' "$f" )

ou

size=$( wc -c "$f" | awk '{print $1}' )

As outras respostas funcionam bem no Linux, mas não no Mac:

  • dunão tem uma -bopção no Mac e o truque BLOCKSIZE = 1 não funciona ("o tamanho mínimo do bloco é 512", o que leva a um resultado errado)

  • cut -d' ' -f1 não funciona porque no Mac, o número pode estar alinhado à direita, preenchido com espaços à frente.

Então, se você precisa de algo flexível, ou é perl's -soperador ou wc -ccanalizada para awk '{print $1}'(awk irá ignorar o espaço em branco à esquerda).

E, é claro, com relação ao restante da sua pergunta original, use o operador -lt(ou -gt):

if [ $size -lt $your_wanted_size ]; then etc.


3
+1; se você souber que só usará o tamanho em um contexto aritmético (onde o espaço em branco à esquerda é ignorado), você pode simplificar size=$(wc -c < "$f")(observe o <que faz wccom que apenas relate um número). Re comparação: não se esqueça do mais "bash-ful" if (( size < your_wanted_size )); then ...(e também [[ $size -lt $your_wanted_size ]]).
— mklement0

3

Com base na resposta de gniourf_gniourf,

find "file.txt" -size -90k

vai escrever file.txtpara stdout se e somente se o tamanho file.txté menor que 90K, e

encontre "file.txt" -size -90k -exec command \;

executará o comando commandse file.txttiver um tamanho menor que 90K. Eu testei isso no Linux. De find(1),

... argumentos de linha de comando seguinte (os -H, -Le -Popções) são tidas como nomes de arquivos ou diretórios a serem examinados, até o primeiro argumento que começa com '-', ...

(enfase adicionada).


1
ls -l $file | awk '{print $6}'

assumindo que o comando ls reporte o tamanho do arquivo na coluna 6


1

Gostaria de usar du's --thresholdpara isso. Não tenho certeza se esta opção está disponível em todas as versões, dumas está implementada na versão do GNU.

Citando o manual do du (1) :

-t, --threshold=SIZE
       exclude entries smaller than SIZE if positive, or entries greater
       than SIZE if negative

Aqui está a minha solução, usando du --threshold=para o caso de uso do OP:

THRESHOLD=90k
if [[ -z "$(du --threshold=${THRESHOLD} file.txt)" ]]; then
    mail -s "file.txt size is below ${THRESHOLD}, please fix. " myemail@gmail.com < /dev/null
    mv -f /root/tmp/file.txt /var/www/file.txt
fi

A vantagem de que, é que dupode aceitar um argumento para essa opção em um formato conhecido - tanto humana como em 10K, 10MiBou o que nunca você se sinta confortável - você não precisa converter manualmente entre formatos / unidades desde dualças que.

Para referência, aqui está a explicação sobre esse SIZEargumento na página de manual:

The SIZE argument is an integer and optional unit (example: 10K is 
10*1024). Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers
of 1000). Binary prefixes can be used, too: KiB=K, MiB=M, and so on.

+1 Excelente opção. Infelizmente, alguns de nós estão presos a versões mais antigas duque não são compatíveis. A --thresholdopção foi adicionada no coreutils 8.21, lançado em 2013 .
— Amit Naidu

1

Ok, se você estiver em um Mac, faça o seguinte: stat -f %z "/Users/Example/config.log" É isso!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.