2015-04-09 22 views
6

Sto provando a correggere uno script che utilizza echo, che sta utilizzando il comando incorporato al posto del comando, come posso impedirlo?Come si impedisce a bash di utilizzare un comando incorporato?

So che posso fare /bin/echo per forzare l'utilizzo di quello, ma non mi piacerebbe hardcode il percorso (per la portabilità).

ho pensato di usare qualcosa come:

$ECHO=`which echo` 
$ECHO -e "text\nhere" 

ma which echo ritorna: "echo: shell built-in comando".


ho finito per definire una funzione che utilizza echoenv come @Kenster raccomanda. In questo modo non ho bisogno di modificare le chiamate per echo nello script.

echo() { 
    env echo $* 
} 

# the function is called before the built-in command. 
echo -en "text\nhere" 
+1

'il comando incorporato al posto del comando' WTF? – ForceBru

+0

Perché non si chiama qualcos'altro? –

+0

@El_Hoy: Solo curioso, qual è l'eco interno 'peggio di'/bin/echo' nel tuo scenario? –

risposta

5

Utilizzare il programma env. Env è un comando che avvia un altro programma con un ambiente eventualmente modificato. Perché env è un programma, non ha accesso ai builtin di shell, agli alias e quant'altro.

Questo comando verrà eseguito il programma di eco, alla ricerca di esso nel vostro percorso di comando:

$ env echo foo 

È possibile verificare questo utilizzando strace per monitorare le chiamate di sistema durante l'esecuzione echo vs env echo:

$ strace -f -e trace=process bash -c 'echo foo' 
execve("/bin/bash", ["bash", "-c", "echo foo"], [/* 16 vars */]) = 0 
arch_prctl(ARCH_SET_FS, 0x7f153fa14700) = 0 
foo 
exit_group(0)       = ? 

$ strace -f -e trace=process bash -c 'env echo foo' 
execve("/bin/bash", ["bash", "-c", "env echo foo"], [/* 16 vars */]) = 0 
arch_prctl(ARCH_SET_FS, 0x7f474eb2e700) = 0 
execve("/usr/bin/env", ["env", "echo", "foo"], [/* 16 vars */]) = 0 
arch_prctl(ARCH_SET_FS, 0x7f60cad15700) = 0 
execve("/usr/local/sbin/echo", ["echo", "foo"], [/* 16 vars */]) = -1 ENOENT (No such file or directory) 
execve("/usr/local/bin/echo", ["echo", "foo"], [/* 16 vars */]) = -1 ENOENT (No such file or directory) 
execve("/usr/sbin/echo", ["echo", "foo"], [/* 16 vars */]) = -1 ENOENT (No such file or directory) 
execve("/usr/bin/echo", ["echo", "foo"], [/* 16 vars */]) = -1 ENOENT (No such file or directory) 
execve("/sbin/echo", ["echo", "foo"], [/* 16 vars */]) = -1 ENOENT (No such file or directory) 
execve("/bin/echo", ["echo", "foo"], [/* 16 vars */]) = 0 
arch_prctl(ARCH_SET_FS, 0x7f0146906700) = 0 
foo 
exit_group(0)       = ? 
+0

Ho finito per usare la soluzione, ma usando una funzione per semplificare l'implementazione: 'echo() {env echo $ *}' funzionava alla grande! – eloyesp

6

È possibile disattivare l'eco incorporato:

enable -n echo 

Ora semplicemente facendo echo anything verrà eseguita la versione esterna. Influisce solo sul processo di script corrente, quindi puoi farlo tranquillamente negli script.

+0

Cool, non lo sapevo. 'Enable' è un comando incorporato? Funziona in 'sh'? – eloyesp

+2

'enable' è incorporato in bash (a meno che non sia abilitato -n enable enable, ovviamente!). Non funziona in POSIX 'sh' perché POSIX non ha una nozione reale di built-in vs external. –

+0

La prima cosa che mi è venuta in mente quando ero 'builtin' e' enable' insieme era 'enable -n enable': D. – Samveen

Problemi correlati