como verificar o diretório está vazio

9

Eu tenho um requisito, se eu executar um script ./123 com argumentos do caminho vazio, digamos /usr/share/linux-headers-3.16.0-34-generic/.tmp_versions (esse diretório está vazio). Deve mostrar "o diretório está vazio"

Meu código é:

#!/bin/bash
dir="$1"

if [ $# -ne 1 ]
then
    echo "please pass arguments" 
exit
fi

if [ -e $dir ]
then
printf "minimum file size: %s\n\t%s\n" \
 $(du $dir -hab | sort -n -r | tail -1)

printf "maximum file size: %s\n\t%s\n" \
 $(du $dir -ab | sort -n | tail -1)

printf "average file size: %s"
du $dir -sk | awk '{s+=$1}END{print s/NR}'
else
   echo " directory doesn't exists"
fi

if [ -d "ls -A $dir" ]
 then
    echo " directory is  empty"
fi

Eu tenho um erro exibido como, se eu executar o nome do script ./123 /usr/src/linux-headers-3.16.0-34-generic/.tmp_versions (este diretório está vazio).

minimum file size: 4096
    /usr/src/linux-headers-3.16.0-34-generic/.tmp_versions
maximum file size: 4096
    /usr/src/linux-headers-3.16.0-34-generic/.tmp_versions
average file size: 4

ao invés de mostrar apenas a saída "o diretório está vazio" mostra a saída acima

A saída abaixo deve ser exibida se eu exceder o script com argumentos corretos (quero dizer, com caminho de diretório correto). diga ./123 /usr/share

minimum file size: 196
        /usr/share
    maximum file size: 14096
        /usr/share
    average file size: 4000

minha saída esperada é: ./123 /usr/src/linux-headers-3.16.0-34-generic/.tmp_versions

directory is empty.
    
por buddha sreekanth 08.05.2015 / 17:17

5 respostas

13

if    ls -1qA ./somedir/ | grep -q .
then  ! echo somedir is not empty
else  echo somedir is empty
fi

O acima é um teste compatível com POSIX - e deve ser muito rápido. ls listará todos os arquivos / dirs em um diretório, exceto . e .. cada um por linha e -q todos os caracteres não imprimíveis (para incluir \n ewlines) na saída com um ponto de interrogação ? . Dessa forma, se grep receber até mesmo um único caractere na entrada, ele retornará true - else false.

Para fazer isso apenas em um POSIX-shell:

cd  ./somedir/ || exit
set ./* ./.[!.]* ./..?*
if   [ -n "$4" ] ||
     for e do 
         [ -L "$e" ] ||
         [ -e "$e" ] && break
     done
then ! echo somedir is not empty
else   echo somedir is empty
fi
cd "$OLDPWD"

Um POSIX-shell (que não desativou anteriormente -f nome_do_arquivo) irá set a "$@" posicional-parâmetro para as seqüências literais seguidas pelo comando set acima, ou então para os campos gerados pelos operadores glob no final de cada um. Se isso acontece, depende se as globs realmente correspondem a alguma coisa. Em alguns shells, você pode instruir um glob não-resolvente a se expandir para null - ou nada. Isso às vezes pode ser benéfico, mas não é portável e muitas vezes vem com problemas adicionais - como ter que definir opções de shell especiais e depois desativá-las.

O único meio portátil de manipular argumentos com valor nulo envolve variáveis vazias ou não definidas ou ~ tilde-expansões. E o último, por sinal, é muito mais seguro que o primeiro.

Acima do shell, apenas um dos arquivos será testado para -e xistence se nenhum dos três globs especificados resolver mais de uma única correspondência. Portanto, o loop for é executado apenas para três ou menos iterações, e apenas no caso de um diretório vazio, ou no caso de um ou mais dos padrões resolver apenas para um único arquivo. O for também break s se qualquer um dos globs representar um arquivo real - e como eu organizei os globs na ordem do mais provável para o menos provável, ele deveria praticamente sair da primeira iteração toda vez.

De qualquer forma você deve envolver apenas um sistema stat() call - o shell e ls devem ambos precisar apenas de stat() do diretório consultado e listar os arquivos seus dentries relatório que contém. Isso é contrastado pelo comportamento de find , que, em vez disso, stat() de todos os arquivos que você pode listar com ele.

    
por 08.05.2015 / 19:51
5

Com o GNU ou BSDs modernos find , você pode fazer:

if find -- "$dir" -prune -type d -empty | grep -q .; then
  printf '%s\n' "$dir is an empty directory"
else
  printf >&2 '%s\n' "$dir is not empty, or is not a directory" \
                    "or is not readable or searchable in which case" \
                    "you should have seen an error message from find above."
fi

(assume que $dir não se parece com um predicado find ( ! , ( , -name... ).

POSIXly:

if [ -d "$dir" ] && files=$(ls -qAL -- "$dir") && [ -z "$files" ]; then
  printf '%s\n' "$dir is an empty directory"
else
  printf >&2 '%s\n' "$dir is not empty, or is not a directory" \
                    "or is not readable or searchable in which case" \
                    "you should have seen an error message from ls above."
fi
    
por 20.05.2015 / 14:33
4

[-z $dir ] reclama que não há nenhum comando chamado [-z na maioria dos sistemas. Você precisa de espaços ao redor dos colchetes .

[ -z $dir ] é verdadeiro se dir estiver vazio e for falso para a maioria dos outros valores de dir , mas não é confiável, por exemplo, se o valor de dir for = -z ou -o -o -n -n . Sempre use o dobro citações em torno de substituições de comandos (isto também vale para o resto do seu script).

[ -z "$dir" ] testa se o valor da variável dir está vazio. O valor da variável é uma string, que é o caminho para o diretório. Isso não diz nada sobre o diretório em si.

Não há operador para testar se um diretório está vazio, como há para um arquivo regular ( [ -s "$dir" ] é verdadeiro para um diretório, mesmo que esteja vazio). Uma maneira simples de testar se um diretório está vazio é listar seu conteúdo; se você receber um texto vazio, o diretório estará vazio.

if [ -z "$(ls -A -- "$dir")" ]; then …

Em sistemas mais antigos que não têm ls -A , você pode usar ls -a , mas . e .. estão listados.

if [ -z "$(LC_ALL=C ls -a -- "$dir")" = ".
.." ]; then …

(Não indente a linha que começa com .. , pois a cadeia deve conter apenas uma nova linha, não uma nova linha nem um espaço extra.)

    
por 09.05.2015 / 02:39
1

Você está vendo os atributos do próprio diretório.

$ mkdir /tmp/foo
$ ls -ld /tmp/foo
drwxr-xr-x 2 jackman jackman 4096 May  8 11:32 /tmp/foo
# ...........................^^^^

Você quer contar quantos arquivos estão lá:

$ dir=/tmp/foo
$ shopt -s nullglob
$ files=( "$dir"/* "$dir"/.* )
$ echo ${#files[@]}
2
$ printf "%s\n" "${files[@]}"
/tmp/foo/.
/tmp/foo/..

Então, o teste para "diretório está vazio" é:

function is_empty {
    local dir="$1"
    shopt -s nullglob
    local files=( "$dir"/* "$dir"/.* )
    [[ ${#files[@]} -eq 2 ]]
}

Assim:

$ if is_empty /tmp/foo; then echo "it's empty"; else echo "not empty"; fi
it's empty
$ touch /tmp/foo/afile
$ if is_empty /tmp/foo; then echo "it's empty"; else echo "not empty"; fi
not empty
    
por 08.05.2015 / 17:38
0
#/bin/sh

somedir=somedir
list="'echo "$somedir"/*'"

test "$list" = "$somedir/*" && echo "$somedir is empty"

# dot prefixed entries would be skipped though, you have to explicitly check them
    
por 09.10.2015 / 22:34