Come eseguire un alias in uno script di shell?


101

Ho un file eseguibile mpiexec, il cui percorso completo è ~/petsc-3.2-p6/petsc-arch/bin/mpiexec. Dal momento che voglio eseguire questo comando in diverse directory (senza dover riscrivere l'intero percorso), ho impostato un alias nel mio .bashrcfile home :

alias petsc="~/petsc-3.2-p6/petsc-arch/bin/mpiexec"  

che mi consente di eseguire mpiexecfacilmente questo file al prompt dei comandi digitando:

petsc myexecutable

Ho provato a scrivere un file di script della shell, chiamato script, usando il mio nuovo alias petsccome comando. Dopo aver dato al mio script shell le autorizzazioni appropriate (usando chmod), ho provato a eseguire lo script. Tuttavia, mi ha dato il seguente errore:

./script: line 1: petsc: command not found

So che potrei semplicemente scrivere il percorso completo del mpiexecfile, ma è scomodo scrivere il percorso completo ogni volta che voglio scrivere un nuovo script. C'è un modo in cui posso usare il mio alias petscall'interno del file di script? C'è un modo in cui posso modificare il mio .bashrco .bash_profilefarlo accadere?


Che ne dici di aggiungere l'alias a .bash_aliases? Inoltre che ne dici di aliasare il percorso assoluto invece del percorso relativo comealias petsc='/home/user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
Nitin Venkatesh,

@nitstorm: nessuna delle due soluzioni sembra funzionare ... ho ancora lo stesso errore di prima
Paul

Risposte:


74
  1. Nella tua shell script usa il percorso completo piuttosto che un alias.

  2. Nello script della shell, imposta una variabile, sintassi diversa

    petsc='/home/your_user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
    
    $petsc myexecutable
  3. Usa una funzione nel tuo script. Probabilmente meglio se petscè complesso

    function petsc () {
        command 1
        command 2
    }
    
    petsc myexecutable
  4. Fonte i tuoi alias

    shopt -s expand_aliases
    source /home/your_user/.bashrc

Probabilmente non vuoi procurarti il ​​tuo .bashrc, quindi, IMO, uno dei primi 3 sarebbe meglio.


16
Il punto 4 non funziona, a meno che non si utilizzi shopt -s expand_aliaseslo stesso script.
enzotib,

Il tuo suggerimento 2) funziona, ma voglio essere in grado di usare lo stesso comando in più script di shell senza dover scrivere la prima riga petsc = "...". C'è un modo per fare questo?
Paul,

1
@enzotib - grazie, l'ho aggiunto alla mia risposta.
Pantera,

1
Nel punto 2 non si imposta un alias ma una variabile.
pabouk,

1
Non richiesto dall'OP ma rilevante per il titolo della domanda: il punto 2 non funziona con i comandi che contengono |. Qui, usa shopt -s expand_aliases& alias locale, ad es. alias myalias='echo abc|rev'- richiede l'interruzione di linea prima dell'uso (vedi ALIASI in man bash). Punto 4: il file sorgente può impedire l'esecuzione non interattiva, ovvero in uno script. Cercare anticipatamente exito return, ad esempio [ -z "$PS1" ] && return(controlla se il prompt primario non è impostato per indicare la shell non interattiva) o potrebbe esserci un check- iin $-( $-contiene opzioni della shell, isignifica interattivo). Vedi man bashper quelle variabili.
valido dal

62

Gli alias sono deprecati a favore delle funzioni della shell. Dalla bashpagina del manuale:

For almost every purpose, aliases are superseded by shell functions.

Per creare una funzione ed esportarla in subshells, inserisci quanto segue nel tuo ~/.bashrc:

petsc() {
    ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
}
export -f petsc

Quindi puoi chiamare liberamente il tuo comando dai tuoi script.


Funziona quasi ... l'unico problema è che devo essere in grado di passare diversi flag all'eseguibile "mpiexec" ... Ad esempio, devo essere in grado di eseguire qualcosa come "petsc -n 40 myexecutable" con il alias "petsc"
Paul

4
@Paul: ho aggiunto "$@"solo per gestire gli argomenti.
enzotib,

12

Le funzioni e gli alias della shell sono limitati alla shell e non funzionano negli script della shell eseguiti. Alternative per il tuo caso:

  • (se non ti preoccupi di usare mpiexecinvece di petsc) Aggiungi $HOME/petsc-3.2-p6/petsc-arch/binalla tua PATHvariabile. Questo può essere fatto modificando ~/.profilee aggiungendo:

    PATH="$HOME/petsc-3.2-p6/petsc-arch/bin:$PATH"

    Effettua nuovamente l'accesso per applicare queste modifiche

  • Creare la directory ~/bine

    • crea uno script wrapper chiamato petsccontenente:

      #!/bin/sh
      exec ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
    • se il programma lo consente, puoi saltare lo shellscript e creare un collegamento simbolico usando il comando:

      ln -s ~/petsc-3.2-p6/petsc-arch/bin/mpiexec ~/bin/petsc

9

In bash 4 è possibile utilizzare variabile speciale: $BASH_ALIASES.

Per esempio:

$ alias foo="echo test"
$ echo ${BASH_ALIASES[foo]}
echo test
$ echo `${BASH_ALIASES[foo]}` bar
test bar

In alternativa, definire come variabile, quindi utilizzare la sostituzione comando o eval.

Ad esempio, invece di definire l'alias come:

alias foo="echo test"

definirlo come:

foo="echo test"

anziché. Quindi eseguirlo mediante:

find . -type f -exec sh -c "eval $foo" \;

o:

find . -type f -exec sh -c "echo `$foo`" \;

Anche se gli alias sono deprecati a favore delle funzioni della shell, questa risposta è l'unica che dovrebbe essere accettata. Anche il vecchio Debian 8 ha la versione 4 di bash, quindi ${BASH_ALIASES[alias]}è una buona opzione. Altrimenti ho dovuto modificare molte righe dei miei .bash_aliases per applicare altre cose. Grazie.
erm3nda,

8

Puoi forzare bash ad eseguire il tuo script come shell interattiva con il flag -i. Questo dirà al tuo file .bashrc di definire alias e altre funzioni.

Esempio:

~ $ grep ll .bashrc
alias ll='ls -lah'
~ $ cat script.sh 
#!/bin/sh

ll
~ $ bash script.sh 
script.sh: line 3: ll: command not found
~ $ bash -i script.sh
..directory contents..

Ulteriori informazioni:

$ man bash

2
.bashrcviene anche letto durante l'esecuzione del comando SSH non interattivo (ecco perché ha un controllo per l'interattività nella parte superiore)
muru

6
ALIASES
   ...
   Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt (see the description of shopt under SHELL BUILTIN COMMANDS
   below).

Quindi la vera risposta a questa domanda, per coloro che cercano di usare alias reali negli script di shell invece di alternative a loro, è:

#!/bin/bash

shopt -s expand_aliases

alias foo=bar

foo whatever

Per quanto riguarda il motivo per cui vorrei fare questo: a causa di circostanze insolite, ho bisogno di ingannare un Dockerfile nel pensare che sia uno script di shell.


4
  1. In .bash_aliases:

    petsc {
    ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
    }

    Oppure inserisci la funzione .bashrc. Di solito sono memorizzate .bashrcsolo le impostazioni di configurazione di bash.

  2. Nel terminal: source .bash_aliases

  3. Chiamalo: petsc arg(s)

Vantaggio: non è necessario export -f petscin .bash_aliases. Gli alias sono obsoleti ma l'utilizzo .bash_aliasesper le funzioni è ok.


Mi piace questa soluzione, la proverò più tardi
Greenonline,

2
  1. Usa i tuoi alias nello script della shell.
  2. Sorgi il tuo script nella shell corrente e interattiva invece di eseguirla.

Quindi se hai un file chiamato script.shcon i tuoi comandi che include l'uso di alias, digita semplicemente:

source script.sh

@DavidFoerster Questo metodo funziona bene. Il sourcing di uno script con .o sourcebuiiltin fa sì che la shell corrente esegua tutti i comandi in essa contenuti. Se si verifica l'espansione dell'alias nella shell in cui .o sourceviene eseguita, si verifica. Tuttavia, è importante rendersi conto che questo metodo è utile solo a volte, perché spesso è necessario o si desidera eseguire uno script nella propria shell, con il proprio ambiente. Gli script di shell scritti con l'intenzione di essere eseguiti nel solito modo non dovrebbero invece essere reperiti di solito - spesso non funzionano correttamente.
Eliah Kagan,

@EliahKagan: grazie. Ora capisco cosa dovrebbe significare la risposta. Aggiungerò una spiegazione.
David Foerster,

1

(EDIT: funzioni rimosse da quando ho letto male la chiamata di mpiexec.)

Se l'unica cosa di cui hai bisogno è meno battitura, perché non metti semplicemente la cartella in $ PATH? O creare un collegamento simbolico a mpiexec da qualche cartella in $ PATH? O (il mio preferito) metti l'alias in uno script che ottieni nello script chiamante?


1
Il motivo per cui non riesco a inserirlo nel mio $ PATH è perché ho un altro file 'mpiexec' in un'altra directory che è già nel mio $ PATH. Se aggiungo il percorso a questo nuovo 'mpiexec', probabilmente cercherà di eseguirli entrambi ... non è vero?
Paul,

1
Non riesco a capire perché non semplicemente utilizzarlo "$@".
enzotib,

2
Paul, proverà a eseguire quello che è il primo nel PERCORSO, non entrambi.
Unhammer,

enzotib, ah ho letto male il modo in cui è stato chiamato mpiexec, ho pensato che avesse bisogno di tutti gli argomenti come uno.
Modificherò la
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.