Por que estou recebendo "linha 1: $ ': \ r': comando não encontrado"?

13

Eu usei o Cygwin no meu laptop (DOS). Eu tenho uma coleção de scripts dos meus colegas e dos meus. Eu não sou uma pessoa de TI, não conhecedor do Unix. Sigo a sintaxe dos meus colegas e sou capaz de gerenciar algumas coisas simples.

Os scripts funcionaram bem no meu laptop antigo. Acabei de trocar de laptop, instalei o Cygwin. Quando executo meus scripts, eles não funcionam. Aqui está um exemplo da mensagem de erro que recebo:

line 1: $':\r': command not found
line 5: syntax error near unexpected token `$'\r''
line 5: `fi

Aqui estão as 5 principais linhas do meu script

:
iter=1
if [ -f iter.txt ]
   then rm ./iter.txt 
fi  

Alguém pode me explicar como resolver esse problema?

TPham
fonte

Respostas:

28

Você tem finais de linha no estilo do Windows.

O comando no-op :é lido como :<carriage return>, exibido como :\rou mais completamente como $':\r'.

Corra dos2unix scriptnamee você deve ficar bem.


Se você não possui dos2unix, o seguinte deve funcionar em praticamente qualquer lugar (e eu testei no MobaXterm no Windows):

vi -b filename

Em seguida vi, digite:

:%s/\r$//
:x

Você está pronto para ir.


No vim, e é para isso que você está usando o Cygwin vi, existem várias maneiras de fazer isso. Outro envolve a fileformatconfiguração, que pode assumir os valores dosou unix. Altere-o explicitamente após carregar o arquivo com

definir fileformat = unix
ou forçar explicitamente o formato do arquivo ao gravá-lo com

: w + fileformat = unix

Para mais informações, consulte as muitas perguntas e respostas aqui sobre este assunto, incluindo:

Curinga
fonte
Só quero esclarecer: "iter = 1" é o meu contador que será usado para o número de rodadas de um algoritmo matemático que meu modelo precisará repetir mais tarde, além da linha 5. Acabei de publicar as 5 principais linhas que acompanham o mensagem de erro. Todos os comentários e instruções são muito apreciados!
TPham 8/09/17
Eu apenas tentei o comando sugerido "$ tr -d .....", mas há algo errado com o meu laptop. Ele não volta para "$", mas o ">" aparece na tela. Eu tenho que usar contrl C para sair. Depois, testei o script para verificar se o problema foi corrigido, mas ele ainda está lá. Desculpe, meu conhecimento neste campo é muito mínimo! Estou tentando utilizar minha coleção de scripts, pois eles ajudam muito meu trabalho. Obrigado a todos por serem pacientes e prestativos para mim.
TPham 8/09/17
@TPham, veja editar. Se isso funcionar, certifique-se de usar a marca de seleção ao lado da resposta para "aceitá-la". (Aceite a resposta que melhor resolveu seu problema.) Unix.stackexchange.com/help/someone-answers
Wildcard
1
Comandos que são palavras não são realmente mais complicados para um iniciante do que um encantamento misterioso que é quase totalmente pontuação. Isso não precisa de uma resposta separada. Ele apenas precisa desta resposta para mencionar que vimpode fazer isso de duas maneiras, uma das quais usa palavras. Ou, melhor ainda, apontar para onde essa tarefa subordinada foi respondida repetidamente aqui com muito mais detalhes do que qualquer resposta nesta página, incluindo unix.stackexchange.com/questions/88811 apenas para iniciantes.
JdeBP # 9/17
1
Observe que vi -b, de \rqualquer maneira , são extensões do vim. não POSIX, não em nvi, elvis, Solaris vi ...
Stéphane Chazelas
10

Isso ocorre porque o script foi salvo por um editor que usa terminações de linha do DOS (como o Notepad ++, por exemplo). Você precisará removê-los dos seus scripts.

Para fazer isso, use dos2unixno arquivo de script ou

$ tr -d '\r' <script >script.new && mv script.new script

(isso removerá todos os retornos de carro de qualquer lugar no script)


Quanto ao código no script:

:
iter=1
if [ -f iter.txt ]
   then rm ./iter.txt 
fi  

Isso deve ser algo como

iter=1
if [ -f "./$iter.txt" ]; then
   rm "./$iter.txt"
fi

Isso remove o arquivo 1.txtdo diretório atual, se existir. O :comando não faz nada (quase) e pode ser removido. O itervalor da variável deve ser usado como $itere entre aspas. E então possivelmente estou sendo mais explícito do que o necessário ./para dizer que o arquivo precisa ser encontrado no diretório atual.

Se você está planejando para transformar isso em um loop (aqui, apagar todos os arquivos 1.txt, 2.txt..., 10.txt):

iter=1
while [ "$iter" -le 10 ]; then
    if [ -f "./$iter.txt" ]; then
        rm "./$iter.txt"
    fi
    iter=$(( iter + 1 ))
done

Ou, se nos sentirmos sorrateiros / preguiçosos,

rm -f {1..10}.txt

em conchas que entendam a expansão da cinta.

Kusalananda
fonte
3
O Notepad ++ realmente tem a opção de usar quebras de linha do Windows / Mac / Linux. Você só precisa ir ao menu Editar e, em seguida, Conversão EOL-> Unix (LF). Ou você poderia simplesmente duplo clique no canto inferior direito onde diz Windows (CR LF)e alterá-lo paraUnix (LF)
jesse_b
Obrigado a todos por suas instruções. Gostaria de esclarecer: o "iter = 1" é um contador que eu uso, mais tarde, para o meu principal objetivo, além da linha 5.
TPham
@TPham De nada. Eu estava entediado e peguei seu código e deixei minha mente impressionar com ele.
Kusalananda
Or rm -f [1-9].txt 10.txt. Mas isso não é totalmente logicamente equivalente, como se não há arquivos 1-9, mas não é um arquivo chamado literalmente [1-9].txt, em seguida, ele será excluído. : D
Wildcard
5

Seus scripts têm finais de linha incorretos. O Windows usa CR + LF (\ r \ n), o Unix usa LF (\ n) e o Classic MacOS usa CR (\ r). Você precisará alterar as terminações de linha em todos os arquivos afetados, com um editor de texto ou uma ferramenta independente dos2unix.

O FTP e os sistemas de controle de versão, como o SVN, tendem a converter as terminações de linha de maneira apropriada; portanto, convém procurar essas opções para transferir arquivos no futuro.

Se esses arquivos não estiverem sendo transferidos, mas apenas usados ​​em uma única máquina, você encontrará as configurações das terminações de linha no seu editor de texto preferido. A maioria dos anunciados como "para programadores" terá essa opção.

Raposa
fonte
Obrigado a todos por suas instruções úteis. Eu apenas tentei o dos2unix, mas parece que não o tenho. Irá pesquisar e tentar novamente.
TPham 8/09/17
3

Como resposta complementar, deixe-me adicionar algumas notas / dicas ...

Primeiro, para arquivos de texto comuns, é possível determinar facilmente se eles têm final de linha Unix ou DOS usando o filecomando Por exemplo:

$ file test.txt
test.txt: ASCII text, with CRLF line terminators
$ dos2unix test.txt
dos2unix: converting file test.txt to Unix format...
$ file test.txt
test.txt: ASCII text

Observe meu uso de dos2unix. Eu recomendo que você o instale. Dependendo de como você usa o Cygwin, pode ser necessário fazer essa conversão com frequência suficiente para que a conveniência seja bem-vinda. Mais importante ainda, não há chance de erro como você obtém nas edições manuais discutidas aqui.

Para instalar, inicie o executável principal do Cygwin. Esse é aquele com o nome de setup-x86_64.exe ou algo do tipo. Certifique-se de ver uma tela como esta:

insira a descrição da imagem aqui

Como você já fez a instalação principal, poderá clicar em Avançar até obter a tela de seleção. Selecione Completo na lista suspensa e digite "dos2" na caixa de pesquisa e escolha a ferramenta como mostrado aqui:

insira a descrição da imagem aqui

Em seguida, clique em Avançar novamente e deixe a instalação concluída. É isso aí. Diverta-se. Cygwin, com exceção desse inconveniente ocasional, é um pacote incrível.

Camada B
fonte
Muito obrigado pela sua instrução B Layer! Este grupo Stack Exchange é muito útil. Eu realmente aprecio esse apoio.
TPham 12/09/17
1

Se não o dos2unix, também há 'flip'

$ flip -u yourfilename.txt

irá alternar para o uso de terminações de linha unix.

chai
fonte
1

Eu uso o Notepad ++ para editar meus scripts bash (.sh) conectando ao servidor pelo WinSCP
(para configurar o editor WinSCP para o Notepad ++: https://winscp.net/eng/docs/ui_editor_preferences )

Isso é muito prático para abrir arquivos dos servidores para editar / salvar em vez do editor " Vim ".
Quando você abre o arquivo no Notepad ++ , clique duas vezes na 7ª coluna na barra de status na parte inferior e selecione " Unix (LF) ".

insira a descrição da imagem aqui

Além disso, você deve alterar o 8º por Codificação -> Codificar em UTF-8 na barra superior.

Alper t. Turker
fonte
0

Você não precisa alterar a codificação de linha do arquivo real para que o Bash do Cygwin funcione alegremente com as codificações de fim de linha do Mac e do Windows. Há uma opção que você só precisa ativar.

Basta atualizar o seu ~/.bash_profilepara que ele contenha

export SHELLOPTS
set -o igncr

Consulte https://ptolemy.berkeley.edu/projects/chess/softdevel/faq/5.html

swdev
fonte