Exécuter la même commande avec des paramètres différents

8

J'ai un programme pas vraiment permissif avec lequel travailler. Malheureusement, ce programme ne permet pas seulement ce qui suit

"command -a -b -c"

ou

"command -abc"

Je dois donc toujours taper ce qui suit

command -a && command -b && command -c

Je suis sûr qu'il existe un moyen plus efficace de taper cela, mais je ne peux pas le comprendre.

Douda
la source
5
Cela dépendra totalement de la commande. Veuillez l'inclure dans votre question.
joepd
1
Vous avez de nombreuses réponses différentes, mais je parie que vous vous en tiendrez à cmd -a; cmd -b; cmd -clong terme, comme tous les êtres humains.
jimmij
Cette question est trop large sans détails command. Dans le cas général command -a -b -c, command -abcet command -a && command -b && command -cont une signification différente ..
Dmitry Grigoryev

Réponses:

14

Vous pourriez faire:

echo -a -b -c | xargs -n 1 command

Ou:

xargs -n1 command <<< '-a -b -c'

avec quelques coquilles.

Mais attention, cela affecte le stdin de command.

Avec zsh:

autoload zargs # best in ~/.zshrc
zargs -n 1 -- -a -b -c -- command

Ou simplement:

for o (-a -b -c) command $o

Aucun de ceux-ci ne serait abandonné si l'une des commandinvocations échouait (sauf si elle échoue avec l'état de sortie 255).

Pour cela, vous voudriez:

for o (-a -b -c) command $o || break

Cela ne parvient toujours pas à l' $?état de sortie de l' commandappel échoué ). Vous pouvez changer cela en:

(){for o (-a -b -c) command $o || return}

Mais à ce moment-là, c'est déjà plus long que:

command -a && command -b && command -c
Stéphane Chazelas
la source
Merci Stéphane pour cette option. La combinaison de !!: 0 et xargs a fait l'affaire.
Douda
10

Vous pouvez vous référer au premier mot de la ligne de commande précédente ( commanddans votre cas) par expansion de l'historique !!:0, puis vous pouvez simplement y ajouter les arguments nécessaires.

command -a && !!:0 -b && !!:0 -c

Par exemple:

% echo foobar && !!:0 spamegg && !!:0 baz    
echo foobar && echo spamegg && echo baz
foobar
spamegg
baz

Notez que, comme l' a souligné Stéphane Chazelas , cela peut également entraîner des extensions inattendues.

heemayl
la source
1
Exactement ce dont j'avais besoin! Merci beaucoup heemayl
Douda
2
!!:0(dans les shells qui prennent en charge l'expansion de l'historique csh) s'étendra au premier mot de la ligne de commande précédente , et non à la commande précédente.
Stéphane Chazelas du
@ StéphaneChazelas clarifié ..
heemayl
Nous ne savons pas quel était le premier mot de la ligne de commande précédente. Essayez d'entrer uname, puis echo foobar && !!:0 spamegg && !!:0 bazcela se développera echo foobar && uname spamegg && uname baz.
Stéphane Chazelas
2
Une seule !suffit: !:0mais avec @ StéphaneChazelas, les points sont mieux utilisés !#:0là où la !#moyenne La ligne de commande entière a été tapée jusqu'à présent .
Costas
3

Que diriez-vous d'une fonction shell enveloppant une boucle?

yourcmd() {
    local arg
    for arg; do
        thing "$arg" || return
    done
}

Où "chose" est la commande réelle que vous souhaitez invoquer. Alors simplement

yourcmd -a -b -c

Vous pouvez même généraliser cela à n'importe quelle commande:

splitargs() {
    local cmd arg 
    cmd="$1"
    shift
    for arg; do
        "$cmd" "$arg" || return
    done
}

alors

splitargs somecommand -a -b -c
kojiro
la source
1

Au milieu des réponses créatives et perspicaces, voici quelque chose de simple au nom de taper moins de caractères:

# under the assumption that you have a frequently-used set of flags: -a -b -c
alias c='command -a && command -b && command -c'

# slightly more generally, name some aliases according to the set of flags
alias cabc='command -a && command -b && command -c'
alias cdef='command -d && command -e && command -f'

# more generally, just shorten the command name and then pass whatever flags you want
alias c=command
c -e && c -f && c -f
Jeff Schaller
la source
0

Créez un script shell MultiRun , qui prend le premier paramètre comme commande et l'exécute avec les paramètres restants un par un.

./ MultiRun curl ABCD

Votre script doit prendre curl comme commande et exécuter "curl A", "curl B", "curl C", "curl D". Maintenant, parce que votre script est sous contrôle, vous pouvez décider si un échec dans l'une des commandes mettra fin au script ou continuera au paramètre suivant ou attendra l'entrée de l'utilisateur ou autre. Vous pouvez même décider de l'état de sortie de l'ensemble du script, en fonction de l'exécution des commandes individuelles.

Le script MultiRun peut ressembler à ceci:

#! /bin/bash
COMMAND=$1
shift #### Remove COMMAND from existing Parameters
for PARAMETER in "$@" ; #### Process all remaining Parameters
do
  # echo Executing "$COMMAND $PARAMETER" now #### Uncomment this line to see what command is getting executed.
  $COMMAND $PARAMETER
  # Check exit status and take action or wait for user input , if required.
  # read -p "finished executing command. press enter to continue. waiting..." #### Uncomment this line to pause between commands.
done
# Depending on the individual exit statuses , choose your exit status N with "exit $N".


Exécutez maintenant ceci: ./MultiRun echo 1 2 3 4
pour obtenir la sortie de "echo 1", "echo 2", "echo 3", "echo 4" comme ceci:
1
2
3
4

C'est une solution très flexible et réutilisable.

Prem
la source