Como eu escrevo um script para contar o número total de arquivos e diretórios no meu diretório pessoal e depois exibi-lo?

3

A questão está no título tentando fazer isso. Eu quero fazer isso com um loop for . Isto é o que eu tenho até agora, que não funciona.

for home in /home/ {.,/}*; do echo "$home"; done

Eu gostaria de fazer isso de forma não recursiva, se possível.

    
por David Prentice 10.11.2015 / 01:05

3 respostas

1

Existem muitos comandos de nível mais alto que quase farão o que você quer fazer, mas esta é uma boa demonstração de como fazer a mesma coisa em um script de shell. Isso deve funcionar em qualquer sistema que tenha /bin/sh . Não depende de nenhum outro comando.

Você pode salvar este script como qualquer nome de arquivo e, em seguida, digitar sh ./whatever_you_named_it para executá-lo.

Eu dividi isso em duas seções, Listando os arquivos e Contando os arquivos . Listar os arquivos recursivamente é o mais complicado, mas assim que tivermos uma lista, é fácil contá-los.

Listando os arquivos

Esse script lista recursivamente todos os arquivos e diretórios em seu diretório pessoal ou em um diretório que recebe como parâmetro. Sem parâmetros, o padrão é o diretório inicial.

#!/bin/sh

if test $# -eq 0
then
    startdir="$HOME"
else
    startdir="$1"
fi

for f in "$start"/*          # step through all files in the starting directory
do
     echo "$f"               # print the file name
     if test -d "$f"         # is the file a directory? (-d)
     then
        sh "$0" "$f"         # yes call this script with the dir as arg
     fi
done

Vamos discutir cada passo:

  1. Se nenhum parâmetro foi passado para o script, use "$ HOME" como o diretório inicial, caso contrário, use o primeiro parâmetro. ($ # contém o número de parâmetros passados para este script e usamos o comando test embutido do shell para descobrir se é zero):

    if test $# -eq 0
    then
            startdir="$HOME"
    else
            startdir="$1"
    fi
    
  2. Itere os arquivos no seu diretório pessoal. "$HOME"/* expande para todos os arquivos e diretórios não ocultos no nível superior de seu diretório pessoal:

    for f in "$HOME"/*
    do
    
  3. Imprima o nome do arquivo. Eu acho que você sabe echo :

         echo "$f"               # print the file name
    
  4. Chame o comando test do shell integrado com a opção -d . test retornará verdadeiro se o argumento "$f" for um diretório. Isso geralmente é escrito como [ -d "$f" ] por brevidade, mas é realmente um comando. [Procure por "expr de teste" na página sh man]:

        if test -d "$f"         # is the file a directory? (-d)
        then
    
  5. Esta próxima declaração é onde nós recorremos. Começamos uma nova cópia do script atualmente em execução e passamos o nome do diretório atual "$ f" para ele. O $0 expande para o nome do arquivo do script de shell atual. Em vez de digitar algum nome de arquivo aqui, usamos $0 para que esse script funcione mesmo que seu nome seja alterado. Por exemplo, se o script fosse chamado de rlist , você também poderia escrever sh rlist "$f" , mas se o script fosse renomeado, o script não funcionaria mais corretamente, porque ele estaria chamando um script inexistente ou o erro roteiro. [Consulte "Parâmetros especiais" na página sh man]:

            sh "$0" "$f"         # yes call this script with the dir as arg
    
  6. Encerra a instrução if e o loop for .

         fi
    done
    

Contando os arquivos

O script até agora lista os arquivos, mas não os conta. Se você quiser obter uma contagem de todos os arquivos e diretórios, execute:

sh ./scriptname | wc -l

wc -l é o comando "contagem de palavras" e, com a opção -l , conta apenas as linhas. O pipeline acima imprime um número que é o número de arquivos em seu diretório pessoal.

    
por 10.11.2015 / 03:30
3

com find para não tipos de diretório no diretório atual sem recursão:

find . ! -name . -prune ! -type d | grep -c /

... para apenas os diretórios soltarem o segundo estrondo, ou para todos os tipos de arquivos, o teste -type será totalmente eliminado.

é fácil nesse caso porque, sem recursão, só vemos um delimitador de caminho por arquivo e, portanto, não há confusão sobre o que e onde contar. Contar novas linhas quando você deveria contar arquivos pode causar problemas - as duas coisas não estão relacionadas. então o que fazer de outra maneira?

find .//. | grep -c '^\.//\.'

... retornará uma contagem precisa de objetos filhos + este objeto com raiz no diretório atual.

igualmente válido, mas com lógica invertida porque cita novas linhas internamente e provavelmente mais rápido porque precisa apenas de stat() de cada diretório em vez de cada arquivo constituinte:

\ls -1qRA . | grep -Exc \[^/]+

se você eliminar a opção -R para ls , ela também funcionará sem recursão.

é possível, entretanto, que o acima possa retornar uma contagem falsa dependendo dos caracteres multibyte em nomes de arquivos e configurações de localidade incompatíveis. colocar LC_ALL=C em um ambiente ls em conformidade com POSIX protegeria contra isso, e para contagens de profundidade de uma árvore considerável, fazer isso só pode ajudar no que diz respeito ao desempenho, afinal.

    
por 10.11.2015 / 06:17
0

Use encontre :

Quando você diz não-recursivamente, você quis dizer que deseja apenas uma contagem de arquivos / diretórios em / home, mas não em subdiretórios? Se for esse o caso, você pode restringir os resultados ao nível superior com a opção maxdepth .

find /home -maxdepth 1 | wc -l

Usando para:

i=0; for home in ~/*; do (( i++ )); done; echo $i

Observe os espaços entre os parênteses duplos e o i ++ incluso.

    
por 10.11.2015 / 05:26