2009-04-13 5 views
2

J'ai un fichier contenant une liste de commandes unix comme "ls -la/etc/passwd". Je veux parcourir cette liste de commandes et prendre les mesures appropriées.Itérer dans une liste de commandes dans un fichier dans la programmation du shell

Actuellement, mon code est quelque chose comme:

#!/bin/bash 
clear 
for cmds in `cat /tmp/cmd` 
do 
     if [ $cmds ] ; then 
       echo $cmds; 
     fi 
done 

Mais, ce que je reçois est une sortie où les commandes sont réparties dans différentes lignes comme

ls 
-la 
/etc/passwd 
ls 
-la 
/etc/shadow 

et non

ls -la /etc/passwd 
ls -la /etc/shadow 

Des idées?

Répondre

1

Ajouter cette avant votre boucle:

IFS=' 
' 

Ou dans Bash:

IFS=$'\n' 

IFS contient une liste de caractères qui sont utilisés pour diviser l'entrée dans les champs; Par défaut, il inclut des espaces, des tabulations et des sauts de ligne, ce qui explique pourquoi le comportement est incorrect. Le définir sur une nouvelle ligne ne se divisera que sur les nouvelles lignes, ce que vous voulez.

+0

Votre solution a partiellement fonctionné, mais tous les n ont également été utilisés pour diviser les champs d'entrée.Et, il a donné une sortie incorrecte comme /etc/ssh/sshd_co fig svcs -a | grep etwork etstat -a | grep -i liste Comme vous pouvez le voir tous les n ont été perdus et dénotés incohéremment de nouvelles lignes. – Epitaph

+0

Désolé. Il semble que ma version de Bash interprète \ n dans IFS spécialement; en général, cependant, cela ne fonctionnera pas pour mettre une nouvelle ligne dans une chaîne. J'ai édité ma réponse pour être plus portable; vous pouvez mettre un retour à la ligne littéral dans la chaîne, ou utiliser la citation de style C de Bash. –

1

Je crois que vous pouvez aussi le faire (entourer vos accents graves avec des guillemets doubles):

"`cat /tmp/cmds`" 

Peut-être essayer quelque chose comme ça (pas sûr de votre « si » est censé être vérifier - je l'ai modifié pour vous assurer que le cmds de $ var n'a pas été une chaîne vide):

#!/bin/bash 

clear 

for cmds in "`cat cmds.txt`" 
do 
    if [ "$cmds" != '' ]; then 
     echo "$cmds" 
    fi 
done 
+0

J'ai eu une erreur après avoir mis dans les guillemets /tmp/fo: line 6: [: trop d'arguments – Epitaph

+0

Ajout d'un exemple, pas sûr que cela fonctionnera pour vous :) –

1

Si chaque ligne dans le fichier est une commande complète - pas continuations sur plusieurs lignes - vous pouvez alors utiliser read:

while read cmd 
do 
    if [ -z "$cmd" ] 
    then : Empty 
    elif $cmd 
    then : OK 
    else : Oops 
    fi 
done < cmds.txt 

Ou, si vous préférez la construction linéaire et ne nécessitent pas quoi que ce soit de la sous-shell que la boucle while représente dans ce qui suit, vous pouvez utiliser:

cat cmds.txt | 
while read cmd 
do 
    if [ -z "$cmd" ] 
    then : Empty 
    elif $cmd 
    then : OK 
    else : Oops 
    fi 
done 

Notez l'utilisation minutieuse des guillemets autour de la chaîne testée. Je préfère toujours utiliser un opérateur explicite '-z'; il y a ceux qui prétendent que ce n'est pas 100% nécessaire. J'utilise toujours des crochets simples plutôt que doubles - principalement par habitude accumulée plus de 20 ans. Ceux qui ont appris la coquille en utilisant bash ou ksh préfèrent souvent l'opérateur double équerre à la place.

Méfiez-vous des redirections d'E/S, bien sûr.

Aussi, si vous n'avez rien à faire dans les différents alors et les autres clauses, il vous suffit de nourrir cmds.txt à la coquille:

sh cmds.txt 

C'est de loin le moyen le plus fiable de traiter avec des commandes multi-lignes.

Questions connexes