Esses são chamados de operadores de shell e, sim, existem mais deles. Vou dar uma breve visão geral dos mais comuns entre as duas principais classes, operadores de controle e operadores de redirecionamento , e como eles funcionam com relação ao shell bash.
&&
: Usado para criar listas AND, ele permite que você execute um comando apenas se outro sair com êxito.
command1 && command2
Aqui, command2
será executado após a command1
conclusão e somente se command1
for bem-sucedido (se o código de saída for 0). Ambos os comandos são executados em primeiro plano.
Este comando também pode ser escrito
if command1
then command2
else false
fi
ou simplesmente if command1; then command2; fi
se o status de retorno for ignorado.
||
: Usado para criar listas OR, ele permite executar um comando apenas se outro sair sem êxito.
command1 || command2
Aqui, command2
só será executado se houver command1
falha (se ele retornar um status de saída diferente de 0). Ambos os comandos são executados em primeiro plano.
Este comando também pode ser escrito
if command1
then true
else command2
fi
ou de forma mais curta if ! command1; then command2; fi
.
Observe que &&
e ||
são associativos à esquerda; consulte Precedência dos operadores lógicos do shell &&, || Para maiores informações.
!
: É uma palavra reservada que atua como operador "not" (mas deve ter um delimitador), usada para negar o status de retorno de um comando - retorne 0 se o comando retornar um status diferente de zero, retorne 1 se retornar o status 0 Também um NÃO lógico para o test
utilitário.
! command1
[ ! a = a ]
E um verdadeiro operador NOT dentro de Expressões Aritméticas:
$ echo $((!0)) $((!23))
1 0
Isso permite que você controle a entrada e a saída de seus comandos. Eles podem aparecer em qualquer lugar dentro de um comando simples ou podem seguir um comando. Os redirecionamentos são processados na ordem em que aparecem, da esquerda para a direita.
<
: Fornece entrada para um comando.
command < file.txt
O acima será executado command
no conteúdo de file.txt
.
<>
: igual ao acima, mas o arquivo está aberto no modo de leitura + gravação em vez de somente leitura :
command <> file.txt
Se o arquivo não existir, ele será criado.
Esse operador raramente é usado porque os comandos geralmente são lidos apenas pelo stdin, embora possam ser úteis em várias situações específicas .
>
: Direciona a saída de um comando para um arquivo.
command > out.txt
O acima irá salvar a saída de command
como out.txt
. Se o arquivo existir, seu conteúdo será sobrescrito e, se não existir, será criado.
Esse operador também é frequentemente usado para escolher se algo deve ser impresso com erro padrão ou saída padrão :
command >out.txt 2>error.txt
No exemplo acima, >
redirecionará a saída padrão e 2>
redirecionará o erro padrão. A saída também pode ser redirecionada usando 1>
, mas, como esse é o padrão, 1
ele geralmente é omitido e é escrito simplesmente como >
.
Assim, para executar command
no file.txt
e salvar sua saída em out.txt
e quaisquer mensagens de erro em error.txt
que você deve executar:
command < file.txt > out.txt 2> error.txt
>|
: Faz o mesmo que >
, mas substituirá o destino, mesmo que o shell tenha sido configurado para recusar a substituição (com set -C
ou set -o noclobber
).
command >| out.txt
Se out.txt
existir, a saída de command
substituirá seu conteúdo. Se não existir, será criado.
>>
: Faz o mesmo que >
, exceto que, se o arquivo de destino existir, os novos dados serão anexados.
command >> out.txt
Se out.txt
existir, a saída de command
será anexada a ele, depois do que já estiver nele. Se não existir, será criado.
&>
, >&
, >>&
E &>>
: (não padronizada). Redirecione o erro padrão e a saída padrão, substituindo ou anexando, respectivamente.
command &> out.txt
O erro padrão e a saída padrão command
serão salvos out.txt
, substituindo seu conteúdo ou criando-o se ele não existir.
command &>> out.txt
Como acima, exceto que, se out.txt
existir, a saída e o erro de command
serão anexados a ele.
A &>
variante se origina em bash
, enquanto a >&
variante vem do csh (décadas antes). Ambos conflitam com outros operadores de shell POSIX e não devem ser usados em sh
scripts portáteis .
<<
: Um documento aqui. É frequentemente usado para imprimir seqüências de várias linhas.
command << WORD
Text
WORD
Aqui, command
levará tudo até encontrar a próxima ocorrência de WORD
, Text
no exemplo acima, como entrada. Embora WORD
seja frequente EoF
ou variada, pode ser qualquer string alfanumérica (e não apenas) que você desejar. Quando WORD
é citado, o texto no documento aqui é tratado literalmente e nenhuma expansão é executada (em variáveis, por exemplo). Se não estiver entre aspas, as variáveis serão expandidas. Para mais detalhes, consulte o manual do bash .
Se você deseja canalizar a saída command << WORD ... WORD
diretamente para outro comando ou comandos, terá que colocar o canal na mesma linha que << WORD
, não poderá colocá-lo após o WORD final ou na linha seguinte. Por exemplo:
command << WORD | command2 | command3...
Text
WORD
<<<
: Aqui strings, semelhantes aos documentos aqui, mas destinadas a uma única linha. Eles existem apenas na porta Unix ou rc (onde se originou), zsh, algumas implementações de ksh, yash e bash.
command <<< WORD
Tudo o que é dado como WORD
é expandido e seu valor é passado como entrada para command
. Isso geralmente é usado para passar o conteúdo de variáveis como entrada para um comando. Por exemplo:
$ foo="bar"
$ sed 's/a/A/' <<< "$foo"
bAr
# as a short-cut for the standard:
$ printf '%s\n' "$foo" | sed 's/a/A/'
bAr
# or
sed 's/a/A/' << EOF
$foo
EOF
Isso abrange apenas os operadores mais comuns de conchas do tipo Bourne. Alguns shells possuem alguns operadores de redirecionamento adicionais próprios.
bash
. Isso está sendo preparado como uma sessão de perguntas e respostas canônicas para fechar as várias perguntas "O que essa coisa estranha faz" e a maioria delas é de usuários do bash. Espero que outra pessoa participe e responda por conchas que não sejam do bash, mas destacar os específicos do bash faz muito sentido. Vou ter que verificar, porém, não sei o que estão em cima da minha cabeça.&>
,>>>
E<<<
são todos para não-POSIX como é a referência à não-somente caracteres não-alphanum em nome de um aqui-doc. Esta resposta também discute muito pouco sobre como eles funcionam - por exemplo, é quase pior do que inútil falar sobre um comando simples e um comando sem explicar o que são e como o shell decide.false
) e um código de saída 0 indica êxito (nãotrue
). Sempre foi assim e é bastante padrão. Um código de saída diferente de 0 indica um erro em todos os ambientes que conheço.Aviso sobre '>'
Iniciantes em Unix que acabaram de aprender sobre o redirecionamento de E / S (
<
e>
) geralmente tentam coisas comoou
ou, quase equivalente,
(
grep
,sed
,cut
,sort
, Espell
são exemplos de comandos que pessoas são tentadas a usar em construções como estas.) Os usuários são surpreendidos ao descobrir que esses cenários resultar no ficheiro de se tornar vazio.Uma nuance que não parece ser mencionada na outra resposta pode ser encontrada à espreita na primeira frase da seção Redirecionamento do bash (1) :
As cinco primeiras palavras devem estar em negrito, itálico, sublinhado, aumentado, piscando, coloridas em vermelho e marcadas com um ícone, para enfatizar o fato de que o shell executa os redirecionamentos solicitados antes que o comando seja executado . E lembre-se também
Então, neste exemplo:
o shell abre o
roster
arquivo para gravação, truncando-o (ou seja, descartando todo o seu conteúdo), antes que osort
programa comece a ser executado. Naturalmente, nada pode ser feito para recuperar os dados.Alguém poderia ingenuamente esperar que
pode ser melhor. Como o shell lida com os redirecionamentos da esquerda para a direita, ele abre
poem
para leitura (paratr
a entrada padrão) antes de abri-lo para gravação (para saída padrão). Mas isso não ajuda. Mesmo que essa sequência de operações produza dois identificadores de arquivo, ambos apontam para o mesmo arquivo. Quando o shell abre o arquivo para leitura, o conteúdo ainda está lá, mas ainda é bloqueado antes da execução do programa.Então o que fazer sobre isso?
As soluções incluem:
Verifique se o programa que você está executando possui capacidade própria e interna para especificar para onde vai a saída. Isso geralmente é indicado por um token
-o
(ou--output=
). Em particular,é aproximadamente equivalente a
exceto, no primeiro caso, o
sort
programa abre o arquivo de saída. E é inteligente o suficiente para não abrir o arquivo de saída até que depois de ter lido todo o arquivo (s) de entrada.Da mesma forma, pelo menos algumas versões de
sed
ter um-i
(edit i opção n Place) que pode ser usado para escrever a saída de volta para o arquivo de entrada (de novo, após todas as entradas foram lidos). Editores comoed
/ex
,emacs
,pico
, evi
/vim
permitir que o usuário editar um arquivo de texto e salvar o texto editado no arquivo original. Observe queed
(pelo menos) pode ser usado de maneira não interativa.vi
possui um recurso relacionado. Se você digitar , ele gravará o conteúdo do buffer de edição , lerá a saída e o inserirá no buffer (substituindo o conteúdo original).:%!command
Entercommand
Simples mas efetivo:
Isso tem a desvantagem de que, se
input_file
for um link, ele (provavelmente) será substituído por um arquivo separado. Além disso, o novo arquivo será de sua propriedade, com proteções padrão. Em particular, isso implica o risco de que o arquivo acabe sendo legível pelo mundo, mesmo que o originalinput_file
não tenha sido.Variações:
command … input_file > temp_file && cp temp_file input_file && rm temp_file
que ainda (potencialmente) deixará o
temp_file
mundo legível. Melhor ainda:cp input_file temp_file && command … temp_file > input_file && rm temp_file
Eles preservam o status do link, o proprietário e o modo (proteção) do arquivo, potencialmente ao custo de duas vezes mais E / S. (Você pode precisar usar uma opção como
-a
ou-p
ativadacp
para dizer a ela para preservar atributos.)command … input_file > temp_file &&
cp --attributes-only --preserve=all input_file temp_file &&
mv temp_file input_file
(dividido em linhas separadas apenas para facilitar a leitura) Isso preserva o modo do arquivo (e, se você é root, o proprietário), mas o torna propriedade de você (se você não é root) e o torna um novo, arquivo separado.
Este blog (edição "in-loco" de arquivos) sugere e explica
Isso requer que
command
seja capaz de processar a entrada padrão (mas quase todos os filtros podem). O próprio blog chama isso de kludge arriscado e desencoraja seu uso. E isso também criará um novo arquivo separado (não vinculado a nada), de sua propriedade e com permissões padrão.O pacote moreutils possui um comando chamado
sponge
:Veja esta resposta para mais informações.
Aqui está uma coisa que me surpreendeu completamente: o syntaxerror diz :
O seguinte pode funcionar nesse caso:
sort
outr
sem a opção-d
ou-s
), você pode tentar Consulte esta resposta e esta resposta para obter mais informações, incluindo uma explicação do exposto acima, e alternativas que funcionem se for garantido que seu comando produz a mesma quantidade de dados de saída que há entrada ou menos (por exemplo,,grep
oucut
). Essas respostas têm a vantagem de não exigir espaço livre (ou exigir muito pouco). As respostas acima do formulário exigem claramente que haja espaço livre suficiente para o sistema poder manter o arquivo inteiro de entrada (antigo) e o arquivo de saída (novo) simultaneamente; isso não é obviamente verdade para a maioria das outras soluções (por exemplo, e ) também. Exceção: provavelmente exigirá muito espaço livre, porquecommand … input_file > temp_file && …
sed -i
sponge
sort … | dd …
sort
precisa ler todas as suas entradas antes que possa gravar qualquer saída e provavelmente armazena em buffer a maioria dos dados, se não todos, em um arquivo temporário.dd
resposta acima. A sintaxe abre o arquivo nomeado no descritor de arquivos para entrada e saída , sem truncá-lo - uma espécie de combinação de e . Nota: Alguns programas (por exemplo, e ) podem se recusar a executar neste cenário porque podem detectar que a entrada e a saída são o mesmo arquivo. Consulte esta resposta para uma discussão sobre o exposto acima e um script que faça essa resposta funcionar se for garantido que seu comando produz a mesma quantidade de dados de saída que há entrada ou menos . Aviso: eu não testei o script de Peter, por isso não atesto.n<> file
n
n<
n>
cat
grep
Então, qual foi a pergunta?
Este tem sido um tópico popular em U&L; é abordado nas seguintes perguntas:
iconv
substituir o arquivo de entrada pela saída convertida?shuf file > file
deixa um arquivo vazio?sort
comando me fornece um arquivo vazio?tr
stdout para um arquivo... e isso não está contando como Superusuário ou Ask Ubuntu. Eu incorporei muitas informações das respostas às perguntas acima aqui nesta resposta, mas não todas. (Ou seja, para obter mais informações, leia as perguntas listadas acima e suas respostas.)
PS Eu tenho nenhuma afiliação com o blog que citei acima.
fonte
/tmp
.dash
seria o shell de recuperação padrão no Ubuntu e não apenas não entende um<<<
herestring, mas também obtém tubos anônimos para<<
heredocuments e não interfere${TMPDIR:-/tmp}
nisso. propósito em tudo. Veja isto ou isto para obter demonstrações sobre o manuseio de documentos aqui. Também por que a mesma quantidade de saída ou menos aviso?dd … conv=notrunc
e as1<>
respostas nunca truncam o arquivo de saída; portanto, se a saída do comando for menor que a entrada (por exemplo,grep
), haverá alguns bytes do original restante no final do arquivo. E, se a saída é maior que o de entrada (por exemplo,cat -n
,nl
ou (potencialmente)grep -n
), há um risco de sobrescrever os dados antigos antes que você lê-lo.Mais observações sobre
;
,&
,(
e)
Observe que alguns dos comandos na resposta de terdon podem ser nulos. Por exemplo, você pode dizer
(sem
command2
). Isso é equivalente a(ou seja, ele simplesmente roda
command1
em primeiro plano e aguarda a conclusão. Comparativamente,(sem
command2
) será iniciadocommand1
em segundo plano e emitirá outro prompt de shell imediatamente.Em contraste,
command1 &&
,command1 ||
, ecommand1 |
não faz qualquer sentido. Se você digitar um destes, o shell (provavelmente) assumirá que o comando continua em outra linha. Ele exibirá o prompt do shell secundário (continuação), que normalmente é definido como>
e continua lendo. Em um script de shell, ele apenas lerá a próxima linha e anexará ao que já foi lido. (Cuidado: isso pode não ser o que você deseja que aconteça.)Nota: algumas versões de alguns shells podem tratar comandos incompletos como erros. Nesses casos (ou, de fato, em qualquer caso em que você tenha um comando longo), você pode colocar uma barra invertida (
\
) no final de uma linha para dizer ao shell para continuar lendo o comando em outra linha:ou
Como diz o terdon,
(
e)
pode ser usado para agrupar comandos. A afirmação de que eles “não são realmente relevantes” para essa discussão é discutível. Alguns dos comandos na resposta de terdon podem ser grupos de comandos . Por exemplo,faz isso:
command1
e aguarde o término.command2
e aguarde o término.Então, se for
command2
bem sucedido,command3
e aguarde o término.command4
e aguarde o término.Se
command2
falhar, pare de processar a linha de comandos.Parênteses externos,
|
se unem muito firmemente,é equivalente a
e
&&
e||
ligam-se mais apertada do que;
, por issoé equivalente a
ou seja,
command3
será executado independentemente do status de saída decommand1
e / oucommand2
.fonte
;
por si só (ou sem um comando anterior), há um erro de sintaxe, e não uma declaração vazia. Assim; ;
é um erro. (Uma armadilha comum para novos usuários, IMHO). Também:;;
é um delimitador especial, paracase
instruções.;
,&&
,||
,&
, e|
, são erros que eles parecem com nada que os precedem. Terdon também abordou;;
(brevemente) em sua resposta.linebreak
token na gramática do shell POSIX. Portanto, talvez seja seguro dizer que todos os shells compatíveis com POSIX os aceitarão. Eu mantenho minha declaração como um aviso geral; se você encontrar um shell pré-POSIX antigo o suficiente, como um shell Bourne real ou mais antigo, todas as apostas serão desativadas.