Bash scripting: teste para diretório vazio

71

Eu quero testar se um diretório não contém arquivos. Se assim for, vou pular algum processamento.

Eu tentei o seguinte:

if [ ./* == "./*" ]; then
    echo "No new file"
    exit 1
fi

Isso dá o seguinte erro:

line 1: [: too many arguments

Existe uma solução / alternativa?

    
por Anthony Kong 31.10.2011 / 04:47

16 respostas

87
if [ -z "$(ls -A /path/to/dir)" ]; then
   echo "Empty"
else
   echo "Not Empty"
fi

Além disso, seria legal verificar se o diretório existe antes.

    
por 31.10.2011 / 04:53
16
if [ -n "$(find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty 2>/dev/null)" ]; then
    echo "Empty directory"
else
    echo "Not empty or NOT a directory"
fi
    
por 31.10.2011 / 11:53
12

Não há necessidade de contar nada ou globos de casca. Você também pode usar read em combinação com find . Se a saída de find estiver vazia, você retornará false :

if find /some/dir -mindepth 1 | read; then
   echo "dir not empty"
else
   echo "dir empty"
fi

Isso deve ser portável.

    
por 29.10.2013 / 22:07
8
#!/bin/bash
if [ -d /path/to/dir ]; then
    # the directory exists
    [ "$(ls -A /path/to/dir)" ] && echo "Not Empty" || echo "Empty"
else
    # You could check here if /path/to/dir is a file with [ -f /path/to/dir]
fi
    
por 01.11.2011 / 15:51
4

Isso fará o trabalho no diretório de trabalho atual (.):

[ 'ls -1A . | wc -l' -eq 0 ] && echo "Current dir is empty." || echo "Current dir has files (or hidden files) in it."

ou o mesmo comando dividido em três linhas apenas para ser mais legível:

[ 'ls -1A . | wc -l' -eq 0 ] && \
echo "Current dir is empty." || \
echo "Current dir has files (or hidden files) in it."

Basta substituir ls -1A . | wc -l por ls -1A <target-directory> | wc -l se você precisar executá-lo em uma pasta de destino diferente.

Editar : substituí -1a por -1A (veja o comentário do @Daniel)

    
por 31.10.2011 / 11:06
3

Use o seguinte:

count="$( find /path -mindepth 1 -maxdepth 1 | wc -l )"
if [ $count -eq 0 ] ; then
   echo "No new file"
   exit 1
fi

Dessa forma, você é independente do formato de saída de ls . -mindepth ignora o próprio diretório, -maxdepth impede a defesa recursiva em subdiretórios para acelerar as coisas.

    
por 31.10.2011 / 11:17
3

Usando uma matriz:

files=( * .* )
if (( ${#files[@]} == 2 )); then
    # contents of files array is (. ..)
    echo dir is empty
fi
    
por 12.08.2014 / 23:46
3

Uma maneira hacky, mas sem bash, sem PID:

is_empty() {
    test -e "$1/"* 2>/dev/null
    case $? in
        1)   return 0 ;;
        *)   return 1 ;;
    esac
}

Isso tira proveito do fato de que test builtin sai com 2 se receber mais de um argumento depois de -e : Primeiro, "$1"/* glob é expandido por bash. Isso resulta em um argumento por arquivo. Então

  • Se não houver arquivos, o asterisco em test -e "$1"* não será expandir, então o Shell volta a tentar o arquivo chamado * , que retorna 1.

  • ... exceto se realmente houver um arquivo chamado exatamente * , então o asterisco se expande para bem, asterisco, que termina como a mesma chamada acima, ie. test -e "dir/*" , só que desta vez retorna 0. (Obrigado @TrueY para apontar isso.)

  • Se houver um arquivo, test -e "dir/file" é executado, o que retorna 0.

  • Mas se houver mais arquivos que 1, test -e "dir/file1" "dir/file2" é executado, que o bash reporta como erro de uso, ou seja, 2.

case envolve toda a lógica, de modo que apenas o primeiro caso, com 1 status de saída, seja relatado como sucesso.

Possíveis problemas que não verifiquei:

  • Existem mais arquivos do que o número de argumentos permitidos - acho que isso poderia se comportar de forma semelhante ao caso com 2+ arquivos.

  • Ou existe um ficheiro com um nome vazio - não tenho a certeza se é possível em qualquer sano OS / FS.

por 24.10.2014 / 03:23
1

Acho que a melhor solução é:

files=$(shopt -s nullglob; shopt -s dotglob; echo /MYPATH/*)
[[ "$files" ]] || echo "dir empty" 

graças ao link

Esta é uma edição anônima da minha resposta que pode ou não ser útil para alguém: Uma ligeira alteração indica o número de arquivos:

files=$(shopt -s nullglob dotglob; s=(MYPATH/*); echo ${s[*]}) 
echo "MYPATH contains $files files"

Isso funcionará corretamente mesmo que os nomes de arquivos contenham espaços.

    
por 29.10.2013 / 21:57
1
if find "${DIR}" -prune ! -empty -exit 1; then
    echo Empty
else
    echo Not Empty
fi

EDITAR: Eu acho que esta solução funciona bem com o gnu find, depois de um rápido olhar para o implementação . Mas isso pode não funcionar, por exemplo, com achado do netbsd . De fato, aquele usa o campo st_size do stat (2). O manual descreve-o como:

st_size            The size of the file in bytes.  The meaning of the size
                   reported for a directory is file system dependent.
                   Some file systems (e.g. FFS) return the total size used
                   for the directory metadata, possibly including free
                   slots; others (notably ZFS) return the number of
                   entries in the directory.  Some may also return other
                   things or always report zero.

Uma solução melhor, também mais simples, é:

if find "${DIR}" -mindepth 1 -exit 1; then
    echo Empty
else
    echo Not Empty
fi

Além disso, o -prune na primeira solução é inútil.

EDIT: no -exit para o gnu find .. a solução acima é boa para o find do NetBSD. Para o GNU encontrar, isso deve funcionar:

if [ -z "'find \"${DIR}\" -mindepth 1 -exec echo notempty \; -quit'" ]; then
    echo Empty
else
    echo Not Empty
fi
    
por 25.05.2018 / 19:06
1

Com FIND (1) (no Linux e no FreeBSD) você pode olhar de maneira não recursiva em uma entrada de diretório via "-maxdepth 0" e testar se está vazio com "-empty". Aplicado à pergunta que isso dá:

if test -n "$(find ./ -maxdepth 0 -empty)" ; then
    echo "No new file"
    exit 1
fi
    
por 26.09.2018 / 15:50
0

Tudo isso é ótimo - basta transformá-lo em um script para que eu possa verificar diretórios vazios abaixo do atual. O abaixo deve ser colocado em um arquivo chamado 'findempty', colocado no caminho em algum lugar para que o bash possa encontrá-lo e, em seguida, o chmod 755 para ser executado. Pode ser facilmente alterado para suas necessidades específicas, eu acho.

#!/bin/bash
if [ "$#" == "0" ]; then 
find . -maxdepth 1 -type d -exec findempty "{}"  \;
exit
fi

COUNT='ls -1A "$*" | wc -l'
if [ "$COUNT" == "0" ]; then 
echo "$* : $COUNT"
fi
    
por 24.02.2012 / 11:06
0

Este trabalho para mim, para verificar & processa arquivos no diretório ../IN , considerando que o script está no diretório ../Script :

FileTotalCount=0

    for file in ../IN/*; do
    FileTotalCount='expr $FileTotalCount + 1'
done

if test "$file" = "../IN/*"
then

    echo "EXITING: NO files available for processing in ../IN directory. "
    exit

else

  echo "Starting Process: Found ""$FileTotalCount"" files in ../IN directory for processing."

# Rest of the Code
    
por 02.05.2018 / 15:29
0

Que tal testar se o diretório existe e não está vazio em uma declaração if

if [[ -d path/to/dir && -n "$(ls -A path/to/dir)" ]]; then 
  echo "directory exists"
else
  echo "directory doesn't exist"
fi
    
por 20.06.2018 / 11:17
-1

Para qualquer diretório diferente do atual, você pode verificar se está vazio tentando rmdir , porque rmdir tem a garantia de falhar em diretórios não vazios. Se rmdir for bem-sucedido e você realmente quiser que o diretório vazio sobreviva ao teste, apenas mkdir novamente.

Não use este hack se houver outros processos que possam se tornar desconcertados por um diretório que eles sabem sobre deixar de existir brevemente.

Se rmdir não funcionar para você e você estiver testando diretórios que poderiam conter um grande número de arquivos, qualquer solução que dependesse de globalização de shell poderia ficar lenta e / ou entrar em limites de comprimento de linha de comando. Provavelmente, é melhor usar find nesse caso. A solução find mais rápida que consigo pensar é como

is_empty() {
    test -z $(find "$1" -mindepth 1 -printf X -quit)
}

Isso funciona para as versões GNU e BSD de find , mas não para o Solaris, que está faltando a cada um desses operadores find . Ame seu trabalho, Oracle.

    
por 10.01.2018 / 18:12
-3

Você pode tentar remover o diretório e aguardar um erro; rmdir não excluirá o diretório se não estiver vazio.

_path="some/path"
if rmdir $_path >/dev/null 2>&1; then
   mkdir $_path        # create it again
   echo "Empty"
else
   echo "Not empty or doesn't exist"
fi
    
por 08.04.2018 / 22:54

Tags