No Linux, eu uso stat --format="%s" FILE
, mas o Solaris ao qual tenho acesso não tem comando stat. O que devo usar então?
Estou escrevendo scripts Bash e não consigo instalar nenhum software novo no sistema.
Já considerei usar:
perl -e '@x=stat(shift);print $x[7]' FILE
ou mesmo:
ls -nl FILE | awk '{print $5}'
Mas nenhum desses parece sensato - executando Perl apenas para obter o tamanho do arquivo? Ou executando 2 comandos para fazer o mesmo?
Respostas:
wc -c < filename
(abreviação de contagem de palavras,-c
imprime a contagem de bytes) é uma solução POSIX portátil . Apenas o formato de saída pode não ser uniforme entre as plataformas, pois alguns espaços podem ser prefixados (que é o caso do Solaris).Não omita o redirecionamento de entrada. Quando o arquivo é passado como argumento, o nome do arquivo é impresso após a contagem de bytes.
Eu estava preocupado que não funcionasse com arquivos binários, mas funciona bem no Linux e no Solaris. Você pode tentar com
wc -c < /usr/bin/wc
. Além disso, os utilitários POSIX têm garantia de lidar com arquivos binários , a menos que especificado de outra forma explicitamente.fonte
wc -c < file
se você não quiser que o nome do arquivo apareça.wc
em um pipeline deveread()
todo o fluxo para contar os bytes. As soluçõesls
/awk
(e semelhantes) usam uma chamada de sistema para obter o tamanho, que deve ser tempo linear (versus O (tamanho))wc
ser muito lento na última vez que fiz isso em um disco rígido cheio. Foi lento o suficiente para que eu pudesse reescrever o roteiro antes que o primeiro acabasse, vim aqui para lembrar como fiz rs.wc -c
; parece muito mais limpo, masls
+awk
é melhor para velocidade / uso de recursos. Além disso, gostaria apenas de salientar que você realmente precisa pós-processar os resultadoswc
também porque em alguns sistemas haverá um espaço em branco antes do resultado, que você pode precisar remover antes de fazer comparações.wc -c
é ótimo, mas não funcionará se você não tiver acesso de leitura ao arquivo.Acabei escrevendo meu próprio programa (muito pequeno) para exibir apenas o tamanho. Mais informações aqui: http://fwhacking.blogspot.com/2011/03/bfsize-print-file-size-in-bytes-and.html
As duas maneiras mais limpas, na minha opinião, com ferramentas comuns do Linux são:
Mas eu simplesmente não quero digitar parâmetros ou canalizar a saída apenas para obter o tamanho do arquivo, então estou usando meu próprio bfsize.
fonte
stat
é uma opção para elas.wc -c
leva 4090 mseg em um arquivo de 10 MB versus "0" msegstat -c %s
, então concordo que é útil ter soluções alternativas, mesmo quando elas não respondem exatamente à pergunta feita.stat -c %s /usr/bin/stat
stat: illegal option -- c
usage: stat [-FlLnqrsx] [-f format] [-t timefmt] [file ...]
Embora
du
geralmente imprima o uso do disco e não o tamanho real dos dados, GNU coreutilsdu
pode imprimir o "tamanho aparente" do arquivo em bytes:Mas não funcionará em BSD, Solaris, macOS, ...
fonte
brew install coreutils
egdu -b
terá o mesmo efeitowc
precisa ler todo o arquivo antes de dar um resultado,du
é imediato.du -b
em um contexto completamente diferente nadu
lógica .lstat
Ele usa apenas a chamada, portanto, seu desempenho não depende do tamanho do arquivo. Mais curtostat -c '%s'
, mas menos intuitivo e funciona de forma diferente para pastas (tamanho de impressão de cada arquivo dentro).du
pode chegar perto usandodu -A -B1
, mas ainda imprime o resultado em múltiplos de blocos de 1024B. Não conseguiu fazê-lo imprimir a contagem de bytes. Mesmo a configuraçãoBLOCKSIZE=1
no ambiente não ajuda, porque o bloco 512B é usado então.Finalmente, decidi usar ls e expansão de matriz bash:
não é muito bom, mas pelo menos faz apenas 1 fork + execve e não depende de linguagem de programação secundária (perl / ruby / python / qualquer que seja)
fonte
ls -ln FILE | { read _ _ _ _ size _ && echo "$size"; }
não precisa de um fork para a segunda etapa do pipeline, já que usa apenas built-ins, mas o Bash 4.2.37 no Linux faz o fork duas vezes (ainda apenas umexecve
).read _ _ _ _ size _ <<<"$(exec ls -ln /usr/bin/wc)" && echo "$size"
funciona com single fork e single exec, mas usa um arquivo temporário para a here-string. Pode ser tornado portátil substituindo o here-string por here-document compatível com POSX . BTW, observe oexec
no subshell. Sem isso, o Bash executa uma bifurcação para o subshell e outro para o comando executado dentro. Esse é o caso do código que você fornece nesta resposta. também.-l
é supérfluo na presença de-n
. Citando POSIXls
manpage :-n
: Ligue a-l
opção (ell), mas quando se escreve proprietário ou grupo do arquivo, escreva UID numérico do arquivo ou GID ao invés do nome do usuário ou grupo, respectivamente. Desativar os-C
,-m
e-x
opções.Solução mais rápida de plataforma cruzada (usa apenas um único fork () para ls , não tenta contar caracteres reais, não gera awk desnecessário, perl, etc).
Testado em MacOS, Linux - pode exigir pequenas modificações para Solaris:
Se necessário, simplifique o ls argumentos e ajuste o deslocamento em $ {__ ln [3]}.
Nota: seguirá links simbólicos.
fonte
Os BSDs possuem
stat
opções diferentes do GNU coreutils, mas recursos semelhantes.Isso funciona no macOS (testado em 10.12), FreeBSD , NetBSD e OpenBSD .
fonte
stat
utilidade alguma.Ao processar a
ls -n
saída, como uma alternativa aos arrays de shell mal portáveis, você pode usar os argumentos posicionais, que formam o único array e são as únicas variáveis locais no shell padrão. Envolva a substituição de argumentos posicionais em uma função para preservar os argumentos originais em seu script ou função.Isso divide a saída de
ln -dn
acordo com asIFS
configurações atuais da variável de ambiente, atribui-a a argumentos posicionais e ecoa o quinto. O-d
garante que os diretórios sejam manipulados corretamente e-n
garante que os nomes de usuários e grupos não precisam ser resolvidos, ao contrário de-l
. Além disso, nomes de usuários e grupos contendo espaços em branco podem teoricamente quebrar a estrutura de linha esperada; eles geralmente não são permitidos, mas essa possibilidade ainda faz o programador parar e pensar.fonte
Se você usar
find
utilitários de arquivo GNU:Infelizmente, outras implementações de
find
geralmente não suportam-maxdepth
, nem-printf
. Esse é o caso de, por exemplo, Solaris e macOSfind
.fonte
size=$(test -f filename && find filename -printf '%s')
.-maxdepth
destina-se a evitar quefind
seja recursivo (jástat
que o que o OP precisa substituir não é). Seufind
comando está sem um-name
e otest
comando não é necessário.find
pesquisa seus parâmetros recursivamente por arquivos que correspondam a determinados critérios. Se os parâmetros não forem diretórios, a recursão é ... bastante simples. Portanto, primeiro eu testo sefilename
é realmente um arquivo comum existente e, em seguida, imprimo seu tamanho usandofind
aquele que não tem onde recursar.find . -maxdepth 1 -type f -name filename -printf '%s'
funciona apenas se o arquivo estiver no diretório atual e ainda pode examinar cada arquivo no diretório, o que pode ser lento. Melhor uso (ainda mais curto!)find filename -maxdepth 1 -type f -printf '%s'
.Você pode usar o
find
comando para obter algum conjunto de arquivos (aqui os arquivos temporários são extraídos). Depois, você pode usar odu
comando para obter o tamanho de cada arquivo em formato legível por humanos usando-h
switch.RESULTADO:
fonte
Seu primeiro exemplo em Perl não parece irracional para mim.
É por razões como essa que migrei de escrever scripts de shell (em bash / sh etc.) para escrever todos os scripts, exceto os mais triviais em Perl. Descobri que estava tendo que lançar o Perl para requisitos específicos e, à medida que fazia isso mais e mais, percebi que escrever scripts em Perl era provavelmente uma forma mais poderosa (em termos de linguagem e da grande variedade de bibliotecas disponíveis via CPAN ) e uma maneira mais eficiente de conseguir o que eu queria.
Observe que outras linguagens de script de shell (por exemplo, python / ruby) sem dúvida terão recursos semelhantes e você pode querer avaliá-los para seus propósitos. Eu apenas discuto Perl porque é a linguagem que uso e com a qual estou familiarizado.
fonte
se você tiver Perl em seu Solaris, use-o. Caso contrário, ls com awk é sua próxima melhor aposta, já que você não tem stat ou seu find não é GNU find.
fonte
Há um truque que usei no Solaris, se você perguntar o tamanho de mais de um arquivo, ele retorna apenas o tamanho total sem nomes - então inclua um arquivo vazio como / dev / null como o segundo arquivo:
por exemplo, arquivo de comando que você deseja / dev / null
Não consigo lembrar qual comando de tamanho isso funciona para ls / wc / etc - infelizmente não tenho uma caixa solaris para testá-lo.
fonte
no linux você pode usar
du -h $FILE
, isso funciona no solaris também?fonte
Você tentou du -ks | awk '{print $ 1 * 1024}'. Isso pode funcionar.
fonte