O que significa `(backquote / backtick) nos comandos?

160

Me deparei com o seguinte comando:

sudo chown `id -u` /somedir

e me pergunto: qual é o significado do `símbolo. Percebi, por exemplo, que, embora o comando acima funcione bem, o comando abaixo não:

sudo chown 'id -u' /somedir
gws
fonte

Respostas:

201

Este é um truque . Um backtick não é um sinal de cotação. Tem um significado muito especial. Tudo o que você digita entre backticks é avaliado (executado) pelo shell antes do comando principal (como chownem seus exemplos), e a saída dessa execução é usada por esse comando, como se você digitasse essa saída naquele local no linha de comando.

E daí

sudo chown `id -u` /somedir

efetivamente executado (dependendo do seu ID de usuário ) é:

sudo chown 1000 /somedir
  \    \     \     \
   \    \     \     `-- the second argument to "chown" (target directory)
    \    \     `-- your user ID, which is the output of "id -u" command
     \    `-- "chown" command (change ownership of file/directory)
      `-- the "run as root" command; everything after this is run with root privileges

Dê uma olhada nesta pergunta para saber por que, em muitas situações, não é uma boa ideia usar backticks.

Aliás, se você quiser usar literalmente um backtick, por exemplo , em uma string, poderá escapar colocando uma barra invertida ( \) antes dele.

rozcietrzewiacz
fonte
36
Isso explica os backticks muito bem, mas usar $(your expression)é a melhor maneira de fazer a mesma coisa que $()permite aninhar expressões. por exemplo: cd $(dirname $(type -P touch))colocará você em cd no diretório que contém o touchcomando
Khaja Minhajuddin 27/12/11
11
@KhajaMinhajuddin Você está definitivamente certo quanto ao aninhamento - a pergunta acima mencionada aborda isso em detalhes. Mas mesmo que eu ache que é uma boa prática usar $()na maioria das situações, isso não torna os backticks uma coisa pior . Para fins práticos, é preciso admitir que eles são muito mais rápidos para digitar na linha de comando (2 pressionamentos de tecla comparados a pelo menos 5, inclusive Shift).
rozcietrzewiacz
2
@rozcietrzewiacz Sua última observação provavelmente é verdadeira para a maioria dos teclados, mas $( )é definitivamente mais fácil digitar do que ` `pelo menos em um teclado francês.
Jlliagre
1
@KhajaMinhajuddin Você pode aninhar backticks, mas você precisa escapar do 2º nível de backticks e do 2º nível, precisa de 3 backticks, 3º nível, 5 backticks, 4º nível 7, etc.
JustinCB
66

Eu gostaria de acrescentar mais alguns pontos aqui.

O backtick `…`é chamado de substituição de comando . O objetivo da substituição de comando é avaliar o comando que é colocado dentro do backtick e fornecer seu resultado como um argumento para o comando real.

A substituição do comando pode ser feita de duas maneiras, uma $(…)e outra `…`. Ambos funcionam da mesma forma, mas a $(…)forma é moderna e tem mais clareza e legibilidade.

E entao

sudo chown $(id -u) /somedir

pode ser preferido sobre o outro.

E mais uma coisa que você precisa observar aqui é o relacionamento de substituição de comando com as regras de cotação do bash, conforme mencionado no documento do bash .

Se a substituição aparecer entre aspas duplas, a divisão de palavras e a expansão do nome do arquivo não são executadas nos resultados.

Kannan Mohan
fonte
8
Além disso, $(...)ninhos melhor.
Kusalananda
$()e "``"não funcionam da mesma maneira
Kun
10

Uma nota de esclarecimento raramente abordada:

Backticks (às vezes também chamados de Graves, porque também serve como sotaque comum em francês e outros idiomas) substituem apenas a Saída padrão , mas não o Erro padrão.

Então, para continuar o exemplo anterior:

file `which hostname`

funcionará conforme o esperado, mas em:

file `which hostnameX`

whichretornará um erro e essa saída será um erro padrão, em vez de ser substituída na linha de comando ao lado de file; não haverá saída padrão, o que você pode confirmar executando:

which hostnameX

which hostnameX 2>/dev/null

Nesse caso,

file `which hostnameX` 

produzirá duas mensagens de erro (a primeira, devido a, which hostnameXe a segunda logo após a primeira, devido ao próprio arquivo, que descobre que o nome do arquivo está ausente e, portanto, todo o comando

reduzirá essencialmente para apenas:

file

que, é claro, é um mau uso e retornará um erro de uso.

(se você quiser verificar por conta própria, pode tentar:

file `which hostnameX 2>/dev/null`    # just the file-command bad-usage error msg is printed

file `which hostnameX 2>/dev/null` 2>/dev/null  # now nothing is printed on the screen :)
Dave K
fonte
4

O backtick `executa o conteúdo da string incluída, então algo como isto

file `which hostname`

descobrirá o caminho para o comando hostname e, em seguida, informará como foi construído.

O comando que você coloca em sua pergunta é executado id -upara obter o ID do usuário efetivo e altera a propriedade de / somedir para esse usuário.

Julian
fonte
2

Este símbolo significa que tudo o que está dentro é interpretado como resultado desse comando.

por exemplo:

$ls /home
one two
$pwd
/usr/three
$cp `pwd` /home
$ls /home
one two three

O resultado acima resulta no threediretório sendo copiado para o meu /homediretório.

Hanan N.
fonte
1

Os backticks se assemelham a substituição de comando. Esta sintaxe backticks é arcaico, e saber o cifrão com dois parênteses é comum: $().

O que é substituição de comando?

A substituição de comando é uma operação única com sintaxe dedicada para executar um comando e ter sua saída armazenada em uma variável para uso posterior.

Um exemplo com data:

thedate=$(date)

Poderíamos então imprimir o resultado: 'A data é% s \ n' "$ thedate" `.

  1. A sintaxe de substituição de comando é $().
  2. O comando em si é date.
  3. Combinando ambos, obtemos $(date)qual é a sua substituição.
  4. Exibimos o valor de saída mantido pela variável com printf, conforme o comando acima.
user9303970
fonte