Quero testar se um diretório não contém nenhum arquivo. Nesse caso, vou pular algum processamento.
Eu tentei o seguinte:
if [ ./* == "./*" ]; then
echo "No new file"
exit 1
fi
Isso fornece o seguinte erro:
line 1: [: too many arguments
Existe uma solução / alternativa?
Respostas:
Além disso, seria legal verificar se o diretório existe antes.
fonte
&&
e||
simultaneamente! Seecho "Not Empty"
falhar,echo "Empty"
será executado! Experimenteecho "test" && false || echo "fail"
! Sim, eu seiecho
que não falhará, mas se você alterar qualquer outro comando, ficará surpreso![ "$(ls -A /)" ] && touch /non-empty || echo "Empty"
- se você quiser "marcar" os diretórios não vazios com um arquivo criadonon-empty
, falhará e imprimirá "Empty".touch /empty
minha fila?if [ -n "$(ls -A /path/to/dir)" ]; then
... Atualize a resposta antes que alguém cole esse código em seu servidor em algum lugar e um hacker descubra como explorá-lo. Se/path/to/dir
não estiver vazio, os nomes de arquivos serão passados como argumentos aos/bin/test
quais claramente não se destina. Basta adicionar o-n
argumento, problema resolvido. Obrigado!Não há necessidade de contar nada ou globs de concha. Você também pode usar
read
em combinação comfind
. Sefind
a saída estiver vazia, você retornaráfalse
:Isso deve ser portátil.
fonte
echo
chamadas refletem o resultado errado: no meu teste (sob Cygwin)find . -mindepth 1 | read
tinha um código de 141 erro em um dir não vazio, e 0 em um dir vazioread
retorna 0 e para um diretório vazio, 1.set -o pipefail
fonte
-n
está correto e seguro (teste com diretório com espaços no nome, teste com diretório não vazio com o nome '0 = 1').... [ -n "$(find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty 2>/dev/null)" ]; ...
grep
. serverfault.com/questions/225798/…find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty | grep .
e confiar no status de saída do grep. Seja como for, é a resposta certa para essa pergunta.fonte
Isso fará o trabalho no diretório de trabalho atual (.):
ou o mesmo comando dividido em três linhas apenas para ser mais legível:
Substitua
ls -1A . | wc -l
porls -1A <target-directory> | wc -l
se precisar executá-lo em uma pasta de destino diferente.Editar : substituí
-1a
por-1A
(consulte o comentário do Daniel)fonte
ls -A
vez disso. Alguns sistemas de arquivos não têm.
e..
links simbólicos de acordo com os docs.-1
é definitivamente redundante. Mesmo quels
não imprima um item por linha quando será canalizado, isso não afeta a ideia de verificar se produziu zero ou mais linhas.Use o seguinte:
Dessa forma, você é independente do formato de saída
ls
.-mindepth
pula o diretório em si,-maxdepth
evita recursivamente a defesa em subdiretórios para acelerar as coisas.fonte
wc -l
efind
formato de saída (que é razoavelmente simples embora).Usando uma matriz:
fonte
shopt -s nullglob
${#files[@]} == 2
suposição não representa o diretório raiz (você provavelmente não testará se está vazio, mas algum código que não sabe sobre essa limitação).Uma maneira hacky, mas apenas bash, livre de PID:
Isso tira vantagem do fato de que o
test
builtin sai com 2 se receber mais de um argumento depois-e
: Primeiro, o"$1"/*
glob é expandido pelo bash. Isso resulta em um argumento por arquivo. assimSe não houver arquivos, o asterisco
test -e "$1"*
não será expandido; portanto, o Shell voltará ao arquivo nomeado*
, que retorna 1.... exceto se realmente houver um arquivo nomeado exatamente
*
, o asterisco se expandirá para bem, asterisco, que termina como a mesma chamada acima, ou seja.test -e "dir/*"
, desta vez retorna 0. (Obrigado @TrueY por apontar isso.)Se houver um arquivo,
test -e "dir/file"
será executado, que retornará 0.Mas se houver mais arquivos que 1,
test -e "dir/file1" "dir/file2"
é executado, o bash o relata como erro de uso, ou seja, 2.case
envolve toda a lógica para que apenas o primeiro caso, com 1 status de saída, seja relatado como bem-sucedido.Possíveis problemas que não verifiquei:
Existem mais arquivos do que o número de argumentos permitidos - acho que isso pode se comportar de maneira semelhante ao caso com mais de 2 arquivos.
Ou, na verdade, existe um arquivo com um nome vazio - não tenho certeza se é possível em qualquer OS / FS sadio.
fonte
test -e dir/*
será chamado. Se o único arquivo é '*' no diretório, o teste retornará 0. Se houver mais arquivos, ele retornará 2. Portanto, funciona como descrito.Com o FIND (1) (no Linux e FreeBSD), você pode olhar de forma não recursiva para uma entrada de diretório via "-maxdepth 0" e testar se está vazia com "-empty". Aplicado à pergunta que isso fornece:
fonte
Eu acho que a melhor solução é:
graças a https://stackoverflow.com/a/91558/520567
Esta é uma edição anônima da minha resposta que pode ou não ser útil para alguém: Uma ligeira alteração fornece o número de arquivos:
Isso funcionará corretamente, mesmo que os nomes de arquivos contenham espaços.
fonte
EDIT: Eu acho que esta solução funciona bem com o gnu find, depois de uma rápida olhada na implementação . Mas isso pode não funcionar com, por exemplo, a descoberta do netbsd . De fato, esse usa o campo st_size do stat (2). O manual descreve como:
Uma solução melhor, também mais simples, é:
Além disso, a poda na 1ª solução é inútil.
EDIT: no -itit for gnu find ... a solução acima é boa para a localização do NetBSD. Para a localização do GNU, isso deve funcionar:
fonte
-exit
predicado .Tudo isso é ótimo - basta transformá-lo em um script para que eu possa procurar por 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, chmod 755 para executar. Pode ser facilmente alterado para suas necessidades específicas, eu acho.
fonte
Este trabalho para mim, para verificar e processar arquivos no diretório
../IN
, considerando que o script está no../Script
diretório:fonte
Que tal testar se o diretório existe e não está vazio em uma instrução if
fonte
Para qualquer diretório que não seja o atual, você pode verificar se está vazio, tentando
rmdir
, porquermdir
é garantido que falhe para diretórios não vazios. Sermdir
for bem-sucedido, e você realmente deseja que o diretório vazio sobreviva ao teste, é sómkdir
fazê-lo novamente.Não use esse hack se houver outros processos que possam ficar descombolados por um diretório que eles conhecem brevemente deixando de existir.
Se
rmdir
não funcionar para você, e você estiver testando diretórios que possam conter um grande número de arquivos, qualquer solução baseada em globbing de shell poderá ficar lenta e / ou atingir os limites de comprimento da linha de comando. Provavelmente melhor para usarfind
nesse caso. Afind
solução mais rápida em que consigo pensar é comoIsso funciona para as versões GNU e BSD,
find
mas não para o Solaris, que está ausente em cada um dessesfind
operadores. Ame seu trabalho, Oracle.fonte
Você pode tentar remover o diretório e aguardar um erro; O rmdir não excluirá o diretório se ele não estiver vazio.
fonte
rmdir
falhará se eu não tiver permissão para remover o diretório; ou se é um subvolume Btrfs; ou se pertencer a um sistema de arquivos somente leitura. E sermdir
não falhar e formkdir
executado: e se o diretório já removido pertencer a outro usuário? e as permissões (possivelmente não-padrão)? ACL? atributos estendidos? Tudo perdido.