2016-02-17 11 views
7

A volte ho un solo liner che sto ripetendo molte volte per un particolare compito, ma probabilmente non lo userò mai più nella stessa forma. Include un nome di file che sto incollando da un elenco di directory. Da qualche parte in mezzo e la creazione di uno script bash ho pensato che forse avrei potuto solo creare una funzione one-liner nella riga di comando come:Definire la funzione nella riga di comando di unix/linux (ad esempio BASH)

numresults(){ ls "$1"/RealignerTargetCreator | wc -l } 

Ho provato un paio di cose come l'utilizzo di eval, utilizzando numresults=function..., ma rifugio' t inciampato sulla sintassi giusta, e non ho trovato nulla sul web finora. (Tutto in arrivo è solo tutorial su funzioni bash).

+0

dimmi il numero di file nella directory '$ 1/RealignerTargetCreator'. – abalter

risposta

8

Citando my answer per una domanda simile su Ask Ubuntu:

funzioni in bash sono essenzialmente chiamati comandi composti (o codice blocchi). Da man bash:

Compound Commands 
    A compound command is one of the following: 
    ... 
    { list; } 
      list is simply executed in the current shell environment. list 
      must be terminated with a newline or semicolon. This is known 
      as a group command. 

... 
Shell Function Definitions 
    A shell function is an object that is called like a simple command and 
    executes a compound command with a new set of positional parameters. 
    ... [C]ommand is usually a list of commands between { and }, but 
    may be any command listed under Compound Commands above. 

Non c'è alcun motivo dato, è solo la sintassi.

Prova con un punto e virgola dopo wc -l:

numresults(){ ls "$1"/RealignerTargetCreator | wc -l; } 
+0

Beh, è ​​stato semplice! (Intendo il punto e virgola). Di nuovo, è sempre bene avere una comprensione più profonda di come funziona la shell. – abalter

+1

Il punto e virgola è necessario perché '}' non è un carattere di controllo e non termina un comando. Notate 'echo}' semplicemente emette la stringa letterale. – chepner

+0

@chepner Sta solo spingendo la domanda un livello in basso. Coloro che hanno creato la grammatica potrebbero rendere '}' speciale per le funzioni. zsh, ad esempio, non ha problemi con 'foo() {echo pippo}'. – muru

3

Non utilizzare ls | wc -l in quanto può dare risultati sbagliati se i nomi dei file hanno a capo in esso. Puoi utilizzare questa funzione al posto di:

numresults() { find "$1" -mindepth 1 -printf '.' | wc -c; } 
+0

Grazie. È sempre bene approfondire le proprie abilità di bash! Solo curioso, come potrebbe un nome di file avere una nuova riga in esso? – abalter

+0

Puoi usare il 'touch $ 'file \ ncon \ nline'' per creare un nome file con newline – anubhava

+1

Questo è decisamente malvagio. – abalter

-2

Il modo più semplice è forse quello di riecheggiare ciò che desideri.

function myfunc() 
{ 
    local myresult='some value' 
    echo "$myresult" 
} 

result=$(myfunc) # or result=`myfunc` 
echo $result 

Comunque here è possibile trovare un buon how-to per scopi più avanzati

2

Si può anche contare i file senza find. Uso degli array,

numresults() { local files=("$1"/*); echo "${#files[@]}"; } 

o utilizzando parametri posizionali

numresults() { set -- "$1"/*; echo "$#"; } 

far corrispondere i file nascosti e,

numresults() { local files=("$1"/* "$1"/.*); echo $(("${#files[@]}" - 2)); } 
numresults() { set -- "$1"/* "$1"/.*; echo $(("$#" - 2)); } 

(Sottraendo 2 dal risultato compensa . e ...)

+1

La prima delle funzioni dei file nascosti potrebbe usare 'dotglob', poiché utilizza comunque gli array. – muru

+0

Hm, per qualche ragione mi sono ricordato anche di 'dotglob' matching' .' e '..', ma non lo è. – chepner

Problemi correlati