Si "bash <file>" funciona, ¿por qué "source <file>" arroja un error?

26

Tengo el siguiente script:

#!/bin/bash
set -x
if :; then
    echo a
fi

Si corro bash /tmp/file, ase repite, pero si corro source /tmp/file, obtengo:

bash: /tmp/test: line 6: syntax error: unexpected end of file

La salida:

knezi@holly tmp]$set -x; source /tmp/test; set +x
+ source /tmp/test
++ set -x
bash: /tmp/test: line 6: syntax error: unexpected end of file
+ set +x

knezi@holly tmp]$set -x; command source /tmp/test; set +x
+ set -x
+ command source /tmp/test
+ source /tmp/test
++ set -x
bash: /tmp/test: line 6: syntax error: unexpected end of file
+ set +x

knezi@holly tmp]$bash -c "source /tmp/test"
+ bash -c 'source /tmp/test'
++ :
++ echo a
a


knezi@holly tmp]$od -c /tmp/test
0000000   #   !   /   b   i   n   /   b   a   s   h  \n   s   e   t    
0000020   -   x  \n   i   f       :   ;       t   h   e   n  \n  \t   e
0000040   c   h   o       a  \n   f   i  \n
0000051

Salida de comandos shopt -py set -o: http://pastebin.com/bsqc8aru

Salida de set: http://pastebin.com/S9KpqZAL

declare -fp no produce nada

Pensé que sourcehace lo mismo que bash, pero en lugar de comenzar una nueva sesión, ejecuta el código en la actual. ¿Alguien puede explicarme este error?

Ejecuto bash GNU bash, versión 4.2.53 (1) -release (x86_64-redhat-linux-gnu).

knezi
fuente
1
No, este es el código completo. Las nuevas líneas son 0a.
knezi
2
@Rahul el código hexadecimal del personaje de
salto de
2
Es el $BASH_ENVconjunto?
roaima
2
@PSkocik que es realmente extraño. bash -c "source / tmp / test" funciona.
knezi
55
Ah-ha! Agregue que funciona con bash -csu pregunta. Luego, muéstranos el contenido de tu ~/.bashrcarchivo, probablemente hay algo allí que está arruinando las cosas.
terdon

Respuestas:

75

Puedo reproducir tu comportamiento si alias fi:

$ alias fi=:
+ alias fi=:
$ . ./test
+ . ./test
++ set -x
bash: ./test: line 6: syntax error: unexpected end of file

Funciona cuando lo ejecuta, pero falla cuando lo obtiene porque los alias no están disponibles en shells no interactivos (el tipo de shell que ejecuta scripts de shell). Como se explica en el manual de bash :

Los alias no se expanden cuando el shell no es interactivo, a menos que la expand_aliasesopción del shell se establezca usando shopt(ver The Shopt Builtin ).

Sin embargo, cuando sourcealgo, se ejecuta en su shell actual que, debido a que es interactivo, ya ha cargado los alias y, por lo tanto, el fialias se reconoce y rompe el origen.

muru
fuente
16
Tienes toda la razón. He establecido: alias fi = 'find -type f | xargs grep -H '.
knezi
77
¡Deshazte de eso aliasahora! :)
Mark Stewart
9
Me sorprende que alguien haya logrado resolver un problema tan oscuro. Bien hecho, señor.
MathematicalOrchid
66
@MathematicalOrchid Sospeché que algo tenía un alias (debido al shell interactivo), setse descartó por la salida, y alias if='foo "'(una cita abierta final dio un error sobre la cita faltante, por lo que la última opción fue el alias fi.
muru