Exemplo, para sua diversão:
$ f=/etc/os-release; . $f; cat $f | sed -re 's/(.*)=.*/printf "%20s: %s\\n" "\\$\1" "$\1"/'
printf "%20s: %s\n" "\$NAME" "$NAME"
printf "%20s: %s\n" "\$VERSION" "$VERSION"
printf "%20s: %s\n" "\$ID" "$ID"
printf "%20s: %s\n" "\$ID_LIKE" "$ID_LIKE"
printf "%20s: %s\n" "\$PRETTY_NAME" "$PRETTY_NAME"
printf "%20s: %s\n" "\$VERSION_ID" "$VERSION_ID"
printf "%20s: %s\n" "\$HOME_URL" "$HOME_URL"
printf "%20s: %s\n" "\$SUPPORT_URL" "$SUPPORT_URL"
printf "%20s: %s\n" "\$BUG_REPORT_URL" "$BUG_REPORT_URL"
printf "%20s: %s\n" "\$PRIVACY_POLICY_URL" "$PRIVACY_POLICY_URL"
printf "%20s: %s\n" "\$VERSION_CODENAME" "$VERSION_CODENAME"
printf "%20s: %s\n" "\$UBUNTU_CODENAME" "$UBUNTU_CODENAME"
$
... agora o problema real;
como executo isso no shell local, SEM o uso de um arquivo temporário!?
(então evite qualquer coisa semelhante a ... >z ; . z ; rm z
)
xargs não pode fazer isso (IIUC)
fonte - não tem essa opção
bash - cria um subshell, portanto não verá os valores das variáveis.
Coisas que eu tentei:
$ source <(f=/etc/os-release; . $f; cat $f | sed -re 's/(.*)=.*/printf "%20s: %s\\n" "\\$\1" "$\1"/')
$NAME:
$VERSION:
$ID:
$ID_LIKE:
$PRETTY_NAME:
$VERSION_ID:
$HOME_URL:
$SUPPORT_URL:
$BUG_REPORT_URL:
$PRIVACY_POLICY_URL:
$VERSION_CODENAME:
$UBUNTU_CODENAME:
$ source < <(f=/etc/os-release; . $f; cat $f | sed -re 's/(.*)=.*/printf "%20s: %s\\n" "\\$\1" "$\1"/')
bash: source: filename argument required
source: usage: source filename [arguments]
$ source /dev/fd/0 <(f=/etc/os-release; . $f; cat $f | sed -re 's/(.*)=.*/printf "%20s: %s\n" "\\$\1" "$\1"/')
^C # no output, CTRL-C
$
SAÍDA ESPERADA, e repito - sem uso de arquivo/scripts temporários:
$NAME: Ubuntu
$VERSION: 20.04.4 LTS (Focal Fossa)
$ID: ubuntu
$ID_LIKE: debian
$PRETTY_NAME: Ubuntu 20.04.4 LTS
$VERSION_ID: 20.04
$HOME_URL: https://www.ubuntu.com/
$SUPPORT_URL: https://help.ubuntu.com/
$BUG_REPORT_URL: https://bugs.launchpad.net/ubuntu/
$PRIVACY_POLICY_URL: https://www.ubuntu.com/legal/terms-and-policies/privacy-policy
$VERSION_CODENAME: focal
$UBUNTU_CODENAME: focal
Explicação:
Na minha versão [acima] disso (uma cópia da resposta de @Scott, abaixo) não tenho as variáveis de /etc/os-release inicializadas no shell principal, apenas no subshell. E disso segue que eles não podem ser impressos pelo source <(...)
shell principal.
Portanto, uma versão "corrigida" de trabalho do oneliner é:
f=/etc/os-release; source "$f"; source <( sed <"$f" -re 's/(.*)=.*/printf "%20s: %s\\n" "\\$\1" "$\1"/')
Onde o primeiro source "$f";
inicializa as variáveis, então o subshell produz o código a ser executado pelo source <(...)
. acima
... com o curto .
substituído por source
legibilidade, aqui.
Resposta curta/geral:
A primeira coisa que você tentou foi correta: se
ou Na verdade, no seu exemplo, funcionou corretamente. Não deu os resultados que você queria porque…command-list
é uma lista de comandos que, quando executados, gera um script de shell (ou seja, outra lista de comandos), você pode executar o script (criado dinamicamente) comResposta longa/específica:
… coisas como
$(…)
e<(…)
(e, por falar nisso,(…)
) criam subshells. O problema com a primeira coisa que você tentou é que você está fazendo o. $f
no subshell e executando osprintf
comandos no shell externo. Então a solução é que você precisa fazer o.
no shell externo:Eu adicionei aspas duplas
"$f"
porque é The Right Thing To Do ™; contanto que o valor de$f
não contenha caracteres estranhos, você não precisa deles, estritamente falando. E, “claro”, você pode alterarsource
o acima para outro.
:Deixei o UUOC para você consertar.