Por que o bash substitui o texto da substituição do comando pelo texto posterior?

4

Eu estava tentando analisar algumas configurações do nginx

λ tree sites-enabled/ sites-available/
sites-enabled/
├── bank.cwrcoding.com.conf
├── calendar.cwrcoding.com.conf
├── cloud.cwrcoding.com.conf
├── cwrcoding.com.conf
├── drive.cwrcoding.com.conf
├── groups.cwrcoding.com.conf
├── mail.cwrcoding.com.conf
├── sites.cwrcoding.com.conf
├── studentenverwaltung.cwrcoding.com.conf
├── wekan.cwrcoding.com.conf
└── www.cwrcoding.com.conf
sites-available/
├── bank.cwrcoding.com.conf
├── calendar.cwrcoding.com.conf
├── cloud.cwrcoding.com.conf
├── cwrcoding.com.conf
├── drive.cwrcoding.com.conf
├── groups.cwrcoding.com.conf
├── mail.cwrcoding.com.conf
├── sites.cwrcoding.com.conf
├── studentenverwaltung.cwrcoding.com.conf
├── wekan.cwrcoding.com.conf
└── www.cwrcoding.com.conf

Os arquivos / * de sites ativados contêm uma única linha:

include sites-availabe/cwrcoding.com.conf;

Ao tentar iterar os arquivos / * habilitados para sites, cortando-os e tentando ler o conteúdo deles como arquivos, recebi um erro estranho, então tentei uma solução de trabalho minimalista e comecei a trabalhar a partir daí, mas ainda acontece o seguinte:

λ for enabled in sites-enabled/*
> do
> echo "$(cat "$enabled") |"
> echo ==========
> done
include sites-available/bank.cwrcoding.com.conf; |
==========
 |clude sites-available/calendar.cwrcoding.com.conf;
==========
 |clude sites-available/cloud.cwrcoding.com.conf;
==========
 |clude sites-available/cwrcoding.com.conf;
==========
 |clude sites-available/drive.cwrcoding.com.conf;
==========
 |clude sites-available/groups.cwrcoding.com.conf;
==========
 |clude sites-available/mail.cwrcoding.com.conf;
==========
 |clude sites-available/sites.cwrcoding.com.conf;
==========
 |clude sites-available/studentenverwaltung.cwrcoding.com.conf;
==========
include sites-available/wekan.cwrcoding.com.conf; |
==========
 |clude sites-available/www.cwrcoding.com.conf;
==========

Como você pode ver, na maioria dos sites, os primeiros caracteres da saída cat são substituídos pelo texto que deve ser após a substituição do comando.

Alguém pode explicar o que está acontecendo? Ou eu encontrei algum bug?

Se você quiser dar uma olhada nos arquivos: link

    
por Chris Werner Rau 08.01.2018 / 20:20

1 resposta

9

O problema é que seus arquivos possuem terminações de linha no estilo DOS / Windows. Como uma solução rápida, substitua:

echo "$(cat "$enabled") |"

Com:

echo "$(tr -d '\r' <"$enabled") |"

Aqui, tr remove o caractere de retorno de carro antes que o arquivo seja exibido, evitando o problema.

Se os seus arquivos se destinam a ser usados em um sistema Unix, no entanto, seria melhor remover os retornos de carro dos próprios arquivos usando um dos utilitários dos2unix ou similares.

Exemplo

Vamos criar dois arquivos no estilo DOS:

$ echo 'include sites-availabe/cwrcoding.com.conf;' | unix2dos > sites-enabled/file1
$ echo 'include sites-availabe/cwrcoding.com.conf;' | unix2dos > sites-enabled/file2

Vamos executar o comando original:

$ for enabled in sites-enabled/*; do echo "$(cat "$enabled") |"; echo ==========; done
 |clude sites-availabe/cwrcoding.com.conf;
==========
 |clude sites-availabe/cwrcoding.com.conf;
==========

Observe a saída desconfigurada.

Com tr aplicado, recebemos a saída esperada:

$ for enabled in sites-enabled/*; do echo "$(tr -d '\r' <"$enabled") |"; echo ==========; done
include sites-availabe/cwrcoding.com.conf; |
==========
include sites-availabe/cwrcoding.com.conf; |
==========
    
por 08.01.2018 / 20:30