Perché il mio script Bash non riconosce gli alias?


216

Nel mio ~/.bashrcfile risiedono due definizioni:

  1. commandA, che è un alias per un percorso più lungo
  2. commandB, che è un alias di uno script Bash

Voglio elaborare lo stesso file con questi due comandi, quindi ho scritto il seguente script Bash:


#!/bin/bash

for file in "$@"
    do
    commandA $file
    commandB $file
done

Anche dopo essermi disconnesso dalla sessione e aver effettuato nuovamente l'accesso, Bash mi richiede command not founderrori per entrambi i comandi quando eseguo questo script.

Che cosa sto facendo di sbagliato?


10
A proposito, non è necessario accedere e disconnettersi per far riconoscere un alias. Devi solo farlo source ~/.bashrc.
Tshepang,

Nel mio caso sono stato collegato in remoto dall'agente SSH, dopo aver aggiunto l'alias quando ho chiuso l'agente SSH e ricollegato ha iniziato a funzionare.
dav

Un alias è un modo per abbreviare un comando. (Vengono utilizzati solo nelle shell interattive e non negli script: questa è una delle pochissime differenze tra uno script e una shell interattiva.)
Kris Roofe

Risposte:


117

Prima di tutto, come diceva Ddeimeke, gli alias di default non si espandono in shell non interattive.

Secondo, .bashrcnon viene letto da shell non interattive a meno che non si imposti la BASH_ENVvariabile di ambiente.

Ma soprattutto: non farlo! Per favore? Un giorno sposterai quello script da qualche parte dove non sono impostati gli alias necessari e si romperà di nuovo.

Invece imposta e usa le variabili d'ambiente come scorciatoie nel tuo script:

#!/bin/bash

CMDA=/path/to/gizmo
CMDB=/path/to/huzzah.sh

for file in "$@"
do
    $CMDA "$file"
    $CMDB "$file"
done

5
Quella soluzione non funziona per i soliti aliascasi d'uso. Es alias mv="mv -v --backup=numbered".
Evi1M4chine,

@ Evi1M4chine: Sì. Almeno dopo che ho ripristinato la modifica non necessaria di Gilles. Tuttavia, potrebbe essere meglio utilizzare una variabile diversa per i parametri.

1
Ah, nota la mancanza di virgolette in giro $CMDA/ $CMDB... A parte le variabili maiuscole riservate a bash stesso in bash, e funziona davvero, la mancanza di virgolette mi rende davvero a disagio ... Grazie comunque.
Evi1M4chine,

@ Evi1M4chine: Uh, cosa? 1. Ho rimosso personalmente le virgolette nella modifica più recente. 2. da dove prendi il "riservato a bash stesso" da? questo sarebbe il primo che ne ho sentito parlare. 3. Se questo ti mette a disagio, come ti senti ad usare bash in primo luogo? Ad ogni modo, usa una variabile separata per le opzioni come ti ho detto.

1
@alvas: il presupposto è che gizmonon si trova sul percorso o che esiste un comando con lo stesso nome ma con una priorità più alta. altrimenti potresti semplicemente impostare CMDAsu plain gizmoin primo luogo.

161

Se guardi nella manpage di bash trovi:

Gli alias non vengono espansi quando la shell non è interattiva, a meno che l'opzione shell expand_aliases sia impostata utilizzando shopt (vedere la descrizione di shopt sotto COMANDI INCORPORATI SHELL di seguito).

Quindi metti a

shopt -s expand_aliases

nella tua sceneggiatura.

Assicurati di eseguire il sorgente del file alias dopo averlo impostato nello script.

shopt -s expand_aliases
source ~/.bash_aliases

7
L'ho inserito nella mia sceneggiatura, ma non funziona ancora. Stesso errore
Zaid

5
L'aggiunta shopt -s expand_aliases source ~/.bash_aliasesfunziona perfettamente per me. Spesso c'è una forma di rilevamento interattivo della shell in .bashrc in questo modo: # If not running interactively, don't do anything [ -z "$PS1" ] && return@Zaid, Forse vuoi verificarlo nel file che hai acquistato.
Frank Schubert,

1
eccellente! salvato i miei script !! :) è così difficile leggere / cercare / sfogliare informazioni e manpage nel terminale che ho appena rinunciato molto tempo fa e andare a cercare su internet ...
Aquarius Power

2
Curiosamente, shopt -s expand_aliasesnon deve andare prima della definizione dell'alias ma prima dell'uso dell'alias. Aggiunta a @FrankSchubert: è inoltre possibile eseguire il rilevamento interattivo della shell utilizzando il $-quale contiene le opzioni per la shell, in particolare ise la shell è interattiva.
valido dal

2
questa non è una risposta corretta ... Sourcing dei tuoi alias all'interno della tua sceneggiatura non è la risposta. Il vostro ~/.bash_aliasespotrebbe dipendere da altre cose precedentemente caricato su una shell interattiva ... La cosa più vicina che ho trovato sta cambiando il tuo hashbang per #!/bin/bash -liancora perfetto. Idealmente dovresti usare le funzioni e non gli alias.
Stefanos Kalantzis,

44

Gli alias non possono essere esportati, quindi non sono disponibili negli script di shell in cui non sono definiti. In altre parole, se li definisci in ~/.bashrccui non sono disponibili your_script.sh(a meno che tu non provenga ~/.bashrcdallo script, che non consiglierei ma ci sono modi per farlo correttamente).

Tuttavia, le funzioni possono essere esportate e sarebbero disponibili per gli script di shell eseguiti da un ambiente in cui sono definiti. Questo può essere fatto posizionandolo nel tuo bashrc:

foo ()
{
    echo "Ciao mondo!"
}
export -f foo

Come dice il manuale di Bash, "Per quasi tutti gli scopi, le funzioni di shell sono preferite agli alias".


1
Anche se questo non risponde tecnicamente alla domanda, come dici tu puoi semplicemente sostituirlo alias commandA=...con commandA() { ... }allora export commandAe ottieni un comportamento identico all'alias. Quindi questa è praticamente un'alternativa identica agli alias per quanto ne so che funziona benissimo negli script bash
Phylliida

Il problema qui è quando hai bisogno di un alias a cui passi molte opzioni tra virgolette. per esempio, ad esempio, alias b=bashrende facile fare ciò b -c "echo test | grep test"che sarebbe difficile fare nelle funzioni.
Fmstrat,

@Fmstrat: b () { bash "$@"; }thenb -c "echo test | grep test"
Dennis Williamson

11
[cmd line] > bash -i [your script's file path]

Il iè per interattivo e fonti vostro bashprofilo per te.


-5

Ho scoperto che a volte lo script bash non riconosce nemmeno l'esportazione. Tuttavia, cambiandolo in

#!/bin/sh

per me va bene.


1
No, non ha ...
Hafiz Temuri,
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.