Como eu imprimo o tamanho do byte de cada arquivo no meu script Bash? [fechadas]

2

Meu código atual é assim:

scan.sh:

#!/bin/bash
while IFS= read -r line;
do
    byte = $(stat -c%s "$line");
    echo "$line : $byte";
done< <(ls *.$1)

A saída seria assim:

./scan.sh cpp
./scan.sh: line 4: byte: command not found
arraysum.cpp :
./scan.sh: line 4: byte: command not found
countLines.cpp :
./scan.sh: line 4: byte: command not found
createtext.cpp :
./scan.sh: line 4: byte: command not found
multiproc1.cpp :
./scan.sh: line 4: byte: command not found
myWc.cpp :
./scan.sh: line 4: byte: command not found
test.cpp :

Basicamente, meu código terá uma sintaxe e pesquisará o diretório com base nessa sintaxe. O problema é que eu quero imprimir "nome do arquivo" + "byte tamanho do arquivo", apenas eu não consigo fazer isso funcionar.

    
por Li Wang 06.10.2018 / 22:34

2 respostas

7

Na sintaxe de shells parecidos com o Bourne, como bash , não deve haver nenhum espaço em torno das atribuições do = nas atribuições.

byte=value

Aqui, analisar a saída de ls é uma má ideia.

Você pode escrevê-lo:

#! /bin/sh -
stat -c '%n: %s' -- *."$1"

Se você precisa de um loop, apenas escreva:

#! /bin/zsh -
for file in *.$1; do
  stat -c '%n: %s' -- $file
done

Ou se você tiver que usar bash :

#! /bin/bash -
shopt -s failglob
for file in *."$1"; do
  stat -c '%n: %s' -- "$file"
done
    
por 06.10.2018 / 22:41
0

Aqui está uma maneira simples de fazer isso que deve funcionar com o shell Bourne e seus descendentes (incluindo o bash e o ksh) , se você não se importar muito com o formato de saída exato:

$ for file in *; do if [ -f "$file" ] && [ -r "$file" ]; then wc -c "$file"; fi; done
      23 HEAD
     111 config
      73 description

Se você também não se importa muito com erros e casos especiais (nesse caso, boa sorte para você):

$ for file in *; do wc -c $file; done

Notas:

  • Se você está escrevendo isso com bash ou ksh, provavelmente é melhor usar (( )) ou [[ ]] em vez de [ ] . ( fonte ) Além disso, considere usar $(wc -c <"$file") em vez de 'wc -c <"$file"' ). ( fonte )

  • -f testa para ver se o que você está vendo é um arquivo comum (não um diretório, dispositivo, canal, soquete, tty ou, geralmente, alguma coisa estranha que não pode ser dito ter um tamanho em bytes). -r testa que o arquivo é legível, ou seja, que wc tem uma chance de sucesso; Se você está olhando para arquivos ou arquivos enormes que você não pode ler, use stat de acordo com sua versão original e a resposta de Stéphane.

  • As aspas ( "$file" ) são necessárias se algum dos arquivos tiver espaços ou tabulações (por exemplo, um arquivo chamado my stuff.txt ).

  • Se você se preocupa com o formato exato, provavelmente deve usar alguma combinação de 'wc -c <"$file"' (que não imprime o nome do arquivo) e echo ou echo -n (que imprimirá o que quiser) ).

  • Se os arquivos de interesse forem argumentos para um script, use o script "$@" ( ).

Concordo com @ stéphane-chazelas que você não deve analisar a saída de ls ; mas se fizer isso, você não precisará da substituição do processo . Você pode simplesmente ler a saída do comando:

ls | while IFS= read -r blá blá blá

ou, se você quiser recorrer a um diretório:

find blá -type f -print | while IFS= read -r blá blá

ou melhor ainda:

find blá -type f print0 | xargs -o blá blá

onde -print0 e xargs -0 leram corretamente nomes de arquivos com espaços ou tabulações

    
por 07.10.2018 / 05:42