Encontrar com exec não funciona como esperado [fechado]

0

Eu preciso verificar se a pasta existe e se sim, fazer uma ação ou, se não, fazer outra ação. Eu uso encontrar para esta tarefa, mas não consigo descobrir o caminho certo:

find /path/to/destination -maxdepth 1 -type d -name "dir*" -exec bash -c '[[ $1 ]] && echo ok || echo "not ok"' _ {} \;

mas ou parte do bash seciton é mais recente executada, alguma sugestão por quê?

    
por EdiD 15.05.2018 / 17:46

3 respostas

1

Se você quiser ver se há diretórios correspondentes a esse padrão de nome, você pode ter find imprimindo alguma saída fictícia para eles e ver se a saída estava vazia. Por exemplo:

if [[ "$(find -type d -name "dir*" -printf .)" ]] ; then
    echo "some matching directory exists"
else 
    echo "no matching directory exists"
fi

Você também pode ter find executar um comando para os arquivos encontrados, apenas adicionando o -exec bash -c '...' _ {} \; após o -printf . Se o comando não produzir nenhuma saída, isso deve ficar bem.

Ele fica um pouco pior se você precisar capturar a saída do comando iniciado por find e mantê-lo separado da saída fictícia: você precisará de arquivos temporários ou de truques de redirecionamento. Isso deve executar somecmd em quaisquer diretórios correspondidos por find , direcionando a saída das execuções de somecmd para o stdout de scripts e, em seguida, informando se houve alguma correspondência.

exec 3>&1
any=$(find -type d -name "dir*" -printf . -exec bash -c 'somecmd "$1" >&3' _ {} \; )
if [[ "$any" ]] ; then
    echo "matching directories were processed"
else 
    echo "no matching directory exists"
fi
exec 3>&-

É claro que, se o comando iniciado por find sempre produzir a saída, não há necessidade da saída fictícia. Apenas capture o que for que find imprime e veja se estava vazio.

    
por 15.05.2018 / 19:33
3

O -exec será feito apenas para arquivos que correspondam aos critérios anteriores ( -name 'dir*' e -type d ) e uma vez para cada arquivo.

Aqui, você provavelmente desejaria usar zsh e fazer algo como:

dirs=(/path/to/destination/dir*(N/))
if (($#dirs)); then
  echo Found these dirs:
  printf ' - %s\n' $dirs
else
  echo >&2 No dir found
fi

Ou com a versão bash 4.4 ou superior e o GNU find de compatível (que você já deve estar usando quando estiver usando a extensão -maxdepth GNU):

readarray -td '' dirs < <(
  find /path/to/destination -maxdepth 1 -type d -name "dir*" -print0)

if ((${#dirs[@]})); then
  echo Found these dirs:
  printf ' - %s\n' "${dirs[@]}"
else
  echo >&2 No dir found
fi
    
por 15.05.2018 / 17:57
1

É feio, mas no bash:

(shopt -s nullglob; if ! [ -z /path/to/destination/dir*/ ] 2>&-; then  echo ok; else echo not ok; fi)

Com nullglob ativado, /path/to/destination/dir*/ será expandido para:

  • nada se nenhum diretório correspondente for encontrado e, nesse caso, o teste -z será bem-sucedido e, portanto, o teste negado falhará.
  • ou para a lista de todos os diretórios correspondentes, neste caso:

    • se houver apenas um diretório, o teste -z falhará
    • se houver vários diretórios, o comando de teste falhará, pois -z espera apenas um operando

    e assim o teste negado passa.

Exemplos:

$ if ! [ -z /a* ] 2>&-; then  echo ok; else echo not ok; fi
not ok
$ if ! [ -z /b* ] 2>&-; then  echo ok; else echo not ok; fi # multiple: /bin /boot 
ok
$ if ! [ -z /h* ] 2>&-; then  echo ok; else echo not ok; fi # single: /home
ok

Este é um caso em que o teste estendido não pode ser usado, já que globbing não acontece em [[ ... ]] .

    
por 15.05.2018 / 18:19

Tags