AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / computer / Perguntas / 1607629
Accepted
Dr. Gut
Dr. Gut
Asked: 2020-12-06 13:40:30 +0800 CST2020-12-06 13:40:30 +0800 CST 2020-12-06 13:40:30 +0800 CST

Como suprimir mensagens de erro no zsh?

  • 772

Em zsh

  • rm foo.barimprime rm: foo.bar: No such file or directory.
  • rm foo.bar 2>/dev/nullimprime nada, como eu esperava.

Mas se o comando contiver correspondências de padrão, o erro não será suprimido por 2>/dev/null:

  • rm *.barimprime zsh: no matches found: *.bar.
  • rm *.bar 2>/dev/nullimprime o mesmo.

Existe uma maneira geral de suprimir mensagens de erro no zsh? Um método simples para todos os tipos de mensagens de erro.

zsh
  • 1 1 respostas
  • 2522 Views

1 respostas

  • Voted
  1. Best Answer
    Kamil Maciorowski
    2020-12-06T16:14:48+08:002020-12-06T16:14:48+08:00

    Quando você tenta executar rm *.bare não há nenhum arquivo que corresponda a *.bar, basicamente duas coisas podem acontecer:

    • O comportamento POSIX é que o shell é executado rmcom literal *.barcomo argumento. A ferramenta tenta remover um arquivo literalmente chamado *.bar(como se você executasse rm '*.bar'), ele falha e imprime algo como rm: *.bar: No such file or directory. É assim que o shell POSIX ( sh) e os shells compatíveis se comportam.

    • O comportamento não POSIX é o shell detecta que não há correspondência, imprime algo como e no matches found: *.barnão é executado rm . É assim que o Zsh se comporta por padrão. (Para comparação: no Bash, você pode alternar para esse comportamento por shopt -s failglob.)

    Um erro de rm(o caso anterior) é impresso no stderr de rm. Um erro do shell (o último caso) é impresso no stderr do shell.

    O redirecionamento em rm *.bar 2>/dev/nullafeta o stderr de rmapenas + . No seu exemplo rmnem roda.

    Para redirecionar o stderr do shell principal, você precisa do exec. Por "o shell principal" quero dizer o shell interativo onde você digita; ou, no caso de execução de um script, o shell interpretando o script. Exemplo:

    exec 2>/dev/null
    

    No Zsh você pode até fechá-lo:

    exec 2>&-
    

    Uma abordagem razoável é duplicar o stderr original antes, caso você precise usá-lo (ou restaurá-lo) mais tarde. Exemplo (observe se você deseja colar este código em um Zsh interativo, então você deve invocar setopt interactive_commentsprimeiro):

    exec 7>&2           # "save" stderr
    exec 2>/dev/null    # redirect
    rm *.bar
    whatever
    exec 2>&7           # restore
    exec 7>&-           # close descriptor which is no longer needed
    

    Aqui 7está um número arbitrário de um dígito, caso contrário, não utilizado como descritor de arquivo. As duas primeiras linhas podem ser escritas como uma: exec 7>&2 2>/dev/null; da mesma forma, as duas últimas linhas podem.

    Note rmou qualquer comando (como whatever) invocado sem redirecionamento stderr herda stderr do shell. Isso significa que no exemplo acima rm(se for executado) e whateverimprimirá suas mensagens de erro (se houver) para /dev/null. Depois exec 2>/dev/nullvocê pode invocar qualquer número ou comandos e todos eles terão /dev/nullcomo stderr. Se você realmente deseja suprimir todos os tipos de mensagens de erro, esse é o caminho.

    A solução funciona em muitos shells, não apenas no Zsh. Se você deseja redirecionar o stderr de um shell interativo, lembre-se de que alguns shells menos sofisticados usam o stderr para imprimir seu prompt.

    Observe que um processo pode redirecionar seu próprio stderr (como nosso shell faz com exec 2>…); ou pode imprimir mensagens de erro para stdout ou para /dev/tty(não deveria, mas tecnicamente pode). Portanto exec 2>/dev/null, não garante que você não verá mensagens que se pareçam com mensagens de erro.

    Depois exec 2>/dev/nullvocê ainda pode redirecionar o stderr de qualquer comando sob demanda. Por exemplo, se em vez disso whatevertivéssemos:

    whatever 2>&7
    

    então suas mensagens de erro iriam para o stderr original que deliberadamente salvamos como descritor de arquivo 7.


    execnão é a única maneira de redirecionar stderr (ou outro descritor de arquivo) de um shell. Você pode tratar um shell (mas não todo o shell principal) como você trata rmem rm … 2>/dev/null. Você pode tratar um subshell assim:

    ( rm *.bar ) 2>/dev/null
    

    ou apenas algum código interpretado pelo shell principal:

    { rm *.bar; } 2>/dev/null
    

    ( ;aqui é opcional no Zsh, obrigatório em alguns outros shells; eu só queria que o código funcionasse fora do Zsh também).

    Qualquer uma dessas linhas pode resolver seu problema. No contexto de suprimir mensagens de erro provenientes de um shell, as duas linhas são equivalentes ++ .

    Observe que o redirecionamento começa em (/ {e termina em )/ }, seu escopo é limitado. Ainda assim, você pode colocar muitos comandos dentro dos parênteses, então o escopo "limitado" pode ser o script inteiro. Ou pode ser apenas uma parte do script (incluindo whateverapresentado anteriormente nesta resposta, o que você quiser). O fato de o redirecionamento parar de funcionar após )/ }torna essa abordagem uma alternativa interessante para salvar e restaurar stderr com exec.


    + Estritamente: afeta " rm" antes e depois de se tornar (ou tentar se tornar) rm. Tenha paciencia comigo. O redirecionamento em rm … 2>/dev/nullcomeça como um redirecionamento executado por um shell bifurcado que está prestes a se substituir por rmexecutável . Este shell redireciona seu próprio stderr antes de tentar se substituir por rm. Qualquer erro reportado após realizar o redirecionamento irá para /dev/null. Por exemplo, se rmnão for encontrado, o redirecionamento já executado suprimirá o command not founderro.

    ++ Tecnicamente ( … )cria um subshell, { … }não. Um subshell se comporta como um processo de shell separado que herda variáveis ​​e diretório de trabalho atual, mas não pode alterar nada (como variáveis ​​ou diretório de trabalho atual) em seu shell pai. Pode ou não ser realizado como um processo verdadeiramente separado, é o comportamento que importa. O OTOH { … }apenas agrupa comandos para algum propósito (no nosso caso o propósito é redirecionamento). Isso não significa que nunca há um subshell quando você usa { … }; por exemplo, em um pipeline, todas as partes, exceto a última, são subshells (em alguns shells: todas as partes, incluindo a última). Esses detalhes técnicos são irrelevantes apenas no contexto do nosso problema, mas em geral podem fazer a diferença.

    • 7

relate perguntas

  • Qual é a diferença entre $path e $PATH do zsh?

  • Alacritty + tmux não pode copiar grande parte do texto no modo de cópia

  • Comportamento estranho para a conclusão automática do zsh

  • substituindo zsh por bash no usuário não root

  • nenhum arquivo ou diretório: /Users/username/.oh-my-zsh/oh-my-zsh.sh

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como posso reduzir o consumo do processo `vmmem`?

    • 11 respostas
  • Marko Smith

    Baixar vídeo do Microsoft Stream

    • 4 respostas
  • Marko Smith

    O Google Chrome DevTools falhou ao analisar o SourceMap: chrome-extension

    • 6 respostas
  • Marko Smith

    O visualizador de fotos do Windows não pode ser executado porque não há memória suficiente?

    • 5 respostas
  • Marko Smith

    Como faço para ativar o WindowsXP agora que o suporte acabou?

    • 6 respostas
  • Marko Smith

    Área de trabalho remota congelando intermitentemente

    • 7 respostas
  • Marko Smith

    O que significa ter uma máscara de sub-rede /32?

    • 6 respostas
  • Marko Smith

    Ponteiro do mouse movendo-se nas teclas de seta pressionadas no Windows?

    • 1 respostas
  • Marko Smith

    O VirtualBox falha ao iniciar com VERR_NEM_VM_CREATE_FAILED

    • 8 respostas
  • Marko Smith

    Os aplicativos não aparecem nas configurações de privacidade da câmera e do microfone no MacBook

    • 5 respostas
  • Martin Hope
    CiaranWelsh Como posso reduzir o consumo do processo `vmmem`? 2020-06-10 02:06:58 +0800 CST
  • Martin Hope
    Jim Pesquisa do Windows 10 não está carregando, mostrando janela em branco 2020-02-06 03:28:26 +0800 CST
  • Martin Hope
    v15 Por que uma conexão de Internet gigabit/s via cabo (coaxial) não oferece velocidades simétricas como fibra? 2020-01-25 08:53:31 +0800 CST
  • Martin Hope
    fixer1234 O "HTTPS Everywhere" ainda é relevante? 2019-10-27 18:06:25 +0800 CST
  • Martin Hope
    andre_ss6 Área de trabalho remota congelando intermitentemente 2019-09-11 12:56:40 +0800 CST
  • Martin Hope
    Riley Carney Por que colocar um ponto após o URL remove as informações de login? 2019-08-06 10:59:24 +0800 CST
  • Martin Hope
    zdimension Ponteiro do mouse movendo-se nas teclas de seta pressionadas no Windows? 2019-08-04 06:39:57 +0800 CST
  • Martin Hope
    jonsca Todos os meus complementos do Firefox foram desativados repentinamente, como posso reativá-los? 2019-05-04 17:58:52 +0800 CST
  • Martin Hope
    MCK É possível criar um código QR usando texto? 2019-04-02 06:32:14 +0800 CST
  • Martin Hope
    SoniEx2 Altere o nome da ramificação padrão do git init 2019-04-01 06:16:56 +0800 CST

Hot tag

windows-10 linux windows microsoft-excel networking ubuntu worksheet-function bash command-line hard-drive

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve