Como @geekosaur explicou, o shell faz o redirecionamento antes de executar o comando. Quando você digita:
sudo foo >/some/file
Seu processo shell atual faz uma cópia de si mesmo que primeiro tenta abrir /some/filepara gravação, depois torna o descritor de arquivo sua saída padrão e só então é executado sudo.
Se você tiver permissão (configurações de sudoer geralmente impedem a execução de shells), você pode fazer algo assim:
sudo bash -c 'foo >/some/file'
Mas acho que uma boa solução em geral é usar em | sudo teevez de >e em | sudo tee -avez de >>. Isso é especialmente útil se o redirecionamento for o único motivo de que preciso sudo; afinal, a execução desnecessária de processos como root é exatamente o que sudofoi criado para evitar. E executar echocomo root é simplesmente idiota.
echo '[archlinuxfr]' | sudo tee -a /etc/pacman.conf >/dev/null
echo 'Server = http://repo.archlinux.fr/$arch' | sudo tee -a /etc/pacman.conf >/dev/null
echo ' ' | sudo tee -a /etc/pacman.conf >/dev/null
Eu adicionei > /dev/nullno final, porque teeenvia sua saída para ambos o arquivo chamado e sua própria saída padrão, e eu não preciso vê-lo no meu terminal. (O teecomando atua como um conector "T" em um pipeline físico, que é de onde vem seu nome.) E eu mudei para aspas simples ( '... ') em vez de duplas ( "... ") para que tudo seja literal e eu não precisou colocar uma barra invertida na frente do $dentro $arch. (Sem as aspas ou barra invertida, $archseria substituído pelo valor do parâmetro do shell arch, que provavelmente não existe, caso em que o $arché substituído por nada e simplesmente desaparece.)
Então isso cuida de gravar arquivos como root usando sudo. Agora, para uma longa digressão sobre as maneiras de produzir texto contendo nova linha em um script de shell. :)
Para BLUF, como eles dizem, minha solução preferida seria apenas alimentar um here-document no sudo teecomando acima ; então não há necessidade de catou echoou printfou quaisquer outros comandos. As aspas simples foram movidas para a introdução da sentinela <<'EOF', mas têm o mesmo efeito lá: o corpo é tratado como texto literal, portanto, $arché deixado sozinho:
sudo tee -a /etc/pacman.conf >/dev/null <<'EOF'
[archlinuxfr]
Server = http://repo.archlinux.fr/$arch
EOF
Mas enquanto eu faria isso, existem alternativas. Aqui estão alguns:
Você pode ficar com um echopor linha, mas agrupar todos eles em um subshell, então você só precisa anexar ao arquivo uma vez:
(echo '[archlinuxfr]'
echo 'Server = http://repo.archlinux.fr/$arch'
echo ' ') | sudo tee -a /etc/pacman.conf >/dev/null
Se você adicionar -eao echo(e estiver usando um shell que suporte essa extensão não POSIX), poderá incorporar novas linhas diretamente na string usando \n:
echo -e '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Mas, como dito acima, esse não é um comportamento especificado pelo POSIX; seu shell pode apenas ecoar um literal -eseguido por uma string com um monte de literais \n. A maneira POSIX de fazer isso é usar em printfvez de echo; ele trata automaticamente seu argumento como o echo -efaz, mas não acrescenta automaticamente uma nova linha no final, então você também precisa colocar um extra \n:
printf '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n \n' |
sudo tee -a /etc/pacman.conf >/dev/null
Com qualquer uma dessas soluções, o que o comando obtém como uma string de argumento contém a sequência de dois caracteres \n, e cabe ao próprio programa de comando (o código dentro de printfou echo) traduzir isso em uma nova linha. Em muitos shells modernos, você tem a opção de usar aspas ANSI $'... ', o que traduzirá as sequências \nem novas linhas literais antes que o programa de comando veja a string. Isso significa que essas strings funcionam com qualquer comando, incluindo o plain old -e-less echo:
echo $'[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Mas, embora mais portáteis do que echo -e, as aspas ANSI ainda são uma extensão não POSIX.
E, novamente, embora essas sejam todas opções, prefiro a tee <<EOFsolução direta acima.