Em zsh, como você redireciona stderr para / dev / null dentro de um loop for ou foreach?

2

Estou tentando realizar algo que é fácil no bash: procure por arquivos em uma pasta e os forneça se eles existirem (e não dê saída se não houver arquivos).

Em bourne shells, isso é como fazer:

  if [ -d /etc/profile.d ]; then
      for f in 'ls -1 /etc/profile.d/*.sh 2> /dev/null'; do
          . $f
      done
  fi

Eu sou novo no zsh e não consigo trabalhar de forma equivalente. O que estou fazendo errado?

if [[ -d "/etc/zsh.d" ]]; then
    for file in (ls -1 /etc/zsh.d/*.zsh 2> /dev/null); do
        source $file
    done
fi

falha: parse error near '>' .

Eu tentei muitas variações e não consegui que fosse tão suave quanto o sh / bash equivalente. É como se o redirecionamento nem sempre funcionasse dentro de sub-unidades.

    
por chrishiestand 12.04.2013 / 00:11

3 respostas

4

Após um e-mail posterior para a lista de discussão dos usuários do zsh, recebi a solução quase ideal para o problema:

if [[ -d "/etc/zsh.d" ]]; then
  for f in /etc/zsh.d/*.zsh(N); do
    source $f
  done
fi

O (N) diz ao zsh para definir a opção NULL_GLOB para esse padrão. Quando nenhuma correspondência é encontrada, o glob se expande para uma string vazia em vez de lançar um erro. Em zsh, um loop for sobre uma expansão vazia não faz nada, que é o comportamento que queremos aqui.

    
por 15.04.2013 / 20:49
3

A análise de ls é uma má ideia .

Em vez disso, você pode usar o shell globbing para obter uma lista de arquivos:

if [[ -d "/etc/zsh.d" ]]; then
  for f in /etc/zsh.d/*.zsh; do
    source $f
  done
fi

Quanto ao redirecionamento, não sei qual é o objetivo dele no seu exemplo, mas se você usar esse método, é o shell que pode lançar um erro, não ls , portanto, execute o redirecionamento após done no loop for .

    
por 12.04.2013 / 14:21
1

Espero que você entenda que quase toda a sintaxe sh funciona bem em zsh?

# Check dir exists then that there are files in it (silently!)
# If there are no .zsh files in /etc/zsh.d then an empty argument
# is passed to for, which then simply skips the loop

if [ -d /etc/zsh.d ]; then
    for file in $(find /etc/zsh.d/ -name '*.zsh'); do
        source $file
    done
fi

Eu tentei fazer isso o mais rápido possível, já que você está em um script de login.

Isso deve funcionar para toda a família Bourne.

    
por 12.04.2013 / 15:03