2009-05-07 11 views
7

Ho un file di nome cmd che contiene un elenco di comandi UNIX come segue:l'esecuzione di comandi che contengono spazio in bash

hostname 
pwd 
ls /tmp 
cat /etc/hostname 
ls -la 
ps -ef | grep java 
cat cmd 

ho un altro script che esegue i comandi in cmd come:

IFS=$'\n' 
clear 
for cmds in `cat cmd` 
do 
     if [ $cmds ] ; then 
     $cmds; 
     echo "****************************"; 
     fi 
done 

Il problema è che i comandi in cmd senza spazi funzionano bene, ma quelli con spazi non sono interpretati correttamente dallo script. Di seguito è riportato l'output:

patrick-laptop 
**************************** 
/home/patrick/bashFiles 
**************************** 
./prog.sh: line 6: ls /tmp: No such file or directory 
**************************** 
./prog.sh: line 6: cat /etc/hostname: No such file or directory 
**************************** 
./prog.sh: line 6: ls -la: command not found 
**************************** 
./prog.sh: line 6: ps -ef | grep java: command not found 
**************************** 
./prog.sh: line 6: cat cmd: command not found 
**************************** 

Cosa mi manca qui?

risposta

13

Provare a cambiare quella linea per eval $cmds piuttosto che solo $cmds

0

EDIT: Il commento di Ben Blank ha sottolineato che la mia vecchia risposta era sbagliata, grazie.

Sembra che tu stia eseguendo i comandi come una singola stringa, quindi bash li vede come il nome dello script/eseguibile.

Un modo per evitare sarebbe invocare bash sul comando. Cambio:

if [ $cmds ] ; then 
    $cmds; 
    echo "****************************"; 
    fi 

a

if [ $cmds ] ; then 
    bash -c $cmds 
    echo "****************************"; 
    fi 
+1

In realtà, sta avendo il problema opposto.Impostare $ IFS come ha fatto qui fa sì che 'for' si intrometta su newline, esattamente come vuole. Tuttavia, sta tentando di interpretare l'intera stringa come un nome di comando piuttosto che un comando con argomenti. –

+0

+1 per offset downvote. :-) –

+0

invocando bash -c stai iniziando un nuovo processo per ogni comando. Sembra eccessivo e potrebbe avere risultati sorprendenti. Ad esempio, se uno dei comandi è un comando cd, i comandi successivi non verranno eseguiti in quell'altra directory. –

1

Edit: Risulta questo non riesce su tubi e reindirizzamento. Grazie, Andomar.

è necessario modificare IFS indietro all'interno del ciclo in modo che bash sa dove a dividere gli argomenti:

IFS=$'\n' 
clear 
for cmds in `cat cmd` 
do 
    if [ $cmds ] ; then 
     IFS=$' \t\n' # the default 
     $cmds; 
     echo "****************************"; 
     IFS=$'\n' 
    fi 
done 
+0

-1, provato, non riesce nel comando "ps -ef | grep java". – Andomar

3

È possibile sostituire lo script con il comando

sh cmd 

Il compito della shell è leggere i comandi ed eseguirli! Se si desidera che gli indicatori di output/progresso, eseguire la shell in modalità dettagliata

sh -v cmd 
2

Personalmente, come questo approccio migliore - Io non voglio munge le IFS se non ho di farlo. Hai bisogno di usare una valutazione se hai intenzione di usare le pipe nei tuoi comandi. La pipa deve essere elaborata dalla shell e non dal comando. Credo che la shell analizzi le pipe prima delle stringhe in espansione.

Si noti che se il file cmd contiene comandi che contengono input, ci sarà un problema. (Ma si può sempre creare un nuovo fd per il comando di lettura da cui leggere.)

clear 
while read cmds 
do 
     if [ -n "$cmds" ] ; then 
     eval $cmds 
     echo "****************************"; 
     fi 
done < cmd 
+0

proDir = $ {PROJECT_DIR}, dove PROJECT_DIR contiene spazio nella directory. Provato con eval $ {PROJECT_DIR} non funziona, qualcuno darà suggerimenti? – arunit21

0
sed 'aecho "-----------"' cmd > cmd.sh; bash cmd.sh 

sed 'Axx' aggiunge i XX ogni linea. Questo non funziona per più righe-comandi come:

for f in * 
do 
    something $f 
fi 

ma per i comandi a riga singola nella maggior parte dei casi, si dovrebbe fare.

Problemi correlati