Em shells POSIX, 'date'
é a forma antiga de substituição de comando. A sintaxe moderna é $(date)
.
Em ambos os casos, eles expandem para a saída de date
com os caracteres de nova linha à direita removidos (desde que a saída não contenha caracteres NUL).
No entanto, quando não estiver entre aspas duplas e em contextos de lista (por exemplo, em argumentos para comandos simples como echo
no seu caso), essa expansão está sujeita a:
-
Divisão de palavras : a saída "de date
com os caracteres de nova linha à direita removidos" é dividida de acordo com o valor atual da variável $IFS
( por padrão, contendo espaço, tabulação e nova linha (e NUL com zsh
)) em várias palavras .
Por exemplo, se date
produzir Fri 1 Nov 14:11:15 GMT 2013\n
(como costuma acontecer em uma localidade inglesa e em um fuso horário britânico continental), e $IFS
atualmente contém :
, isso será dividido em 3 palavras : Fri 1 Nov 14
, 11
e 15 GMT 2013
.
-
Geração de nome de arquivo (também conhecido como globbing ) (exceto com
zsh
): ou seja, cada palavra resultante da divisão acima é procurada por caracteres curinga ( *
, ?
, [...]
embora alguns shells tenham mais) e expandido para a lista de nomes de arquivos que correspondem a esses padrões. Por exemplo, se a saída de date
for ?%? 33 */*/* UVC 3432
(como geralmente é em localidades venusianas e fuso horário UVC) e $IFS
for o valor padrão), isso se expandirá para todos os nomes de arquivos de 3 caracteres não ocultos em o diretório atual cujo caractere do meio é %
, 33
, todos os arquivos não ocultos em todos os subdiretórios não ocultos de todos os subdiretórios não ocultos do diretório atual, UVC
e 3432
.
É por isso que:
- Você deve sempre citar (com aspas duplas) as substituições de comandos, a menos que você queira que a divisão de palavras ou a geração de nome de arquivo sejam executadas na expansão
- Se você quiser divisão de palavras , defina
$IFS
para os caracteres que deseja dividir.
- Se você quiser divisão de palavras , mas não geração de nome de arquivo , precisará emitir um
set +f
para desativá-lo.
As citações simples citam tudo, fazendo com que os caracteres do backtick sejam interpretados literalmente.
Exemplo (usando -x
torna mais fácil ver o que está acontecendo):
$ bash --norc -x
bash-4.2$ IFS=:
+ IFS=:
bash-4.2$ echo 'date'
++ date
+ echo 'Fri 1 Nov 14' 42 '33 GMT 2013'
Fri 1 Nov 14 42 33 GMT 2013
bash-4.2$ echo "'date'"
++ date
+ echo 'Fri 1 Nov 14:42:41 GMT 2013'
Fri 1 Nov 14:42:41 GMT 2013
bash-4.2$ cd /lib/modules
+ cd /lib/modules
bash-4.2$ export TZ=UVC LC_ALL=vs_VS
+ export TZ=UVC LC_ALL=vs_VS
+ TZ=UVC
+ LC_ALL=vs_VS
bash-4.2$ unset -v IFS # get the default behaviour
+ unset -v IFS
bash-4.2$ echo 'date'
++ date
+ echo '?%?' 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
?%? 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
bash-4.2$ echo "'date'"
++ date
+ echo '?%? 33 */*/* UVC 3432'
?%? 33 */*/* UVC 3432
Se a saída contiver caracteres NUL, o comportamento varia de shell para shell: alguns removem-nos, alguns truncam a saída no primeiro caractere NUL, zsh
os preserva, mas observe que, de qualquer maneira, comandos externos não aceitam argumentos contendo NULs