Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 29/12/2010, à 10:49

Zakhar

[Résolu] Existe-t-il une commande qui ne fait rien ?

Tout est dans le titre... ou presque.

J'aimerais savoir s'il y a une commande standard -pour mettre dans un script bash- qui :
- ne fait rien
- prend un nombre quelconque d'arguments
- retourne 0 (succès)
- [Optionnel] qui copie tout ce qui arrive dans stdin vers stdout (un peu comme un "pipe" : | )

... un peu comme la commande assembleur NOP (No Operation) des processeurs -sauf qu'elle ne prend aucun argument-.

Dernière modification par Zakhar (Le 29/12/2010, à 11:25)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#2 Le 29/12/2010, à 11:00

Totor

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Je présume qu'il s'agit de bash ?
tout simplement comme ceci

echo "un affichage juste avant de ne rien faire"
: rien du tout
echo "c'est fini"

cependant, il est possible d'utiliser cette syntaxe pour réaliser des actions de valorisation/vérification de variable.
Pour exemple, valoriser la variable neRienFaire si elle est vide ou non définie :

echo "${neRienFaire}"
: ${neRienFaire:=Rien}
: ${neRienFaire:=TropTard}
echo "${neRienFaire}"

Générer une erreur si la variable n'est pas définie :

unset neRienFaire
: ${neRienFaire:?Variable non définie}

Enfin, si ça ne te convient pas :

function nop() { return 0; }
export -f nop

-- Lucid Lynx --

Hors ligne

#3 Le 29/12/2010, à 11:24

Zakhar

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Parfait, merci totor !..

Le : me convient tout à fait.

... et c'est vrai, je n'avais pas pensé tout simplement à la fonction qui est aussi une autre façon de faire.


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#4 Le 29/12/2010, à 12:52

ehmicky

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Tu peux aussi utiliser "true", qui est un autre mot pour ":" (c'est plutôt l'inverse en fait)

Dernière modification par ehmicky (Le 29/12/2010, à 12:52)


Stego++, bibliothèque libre de stéganographie (avec cryptographie), à venir !
Besoin de votre aide :
Stats sur les compilateurs C++ les plus utilisés
Comment utiliser les archetypes C++ ?

Hors ligne

#5 Le 29/12/2010, à 20:56

Zakhar

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Merci à tous les deux.

En réalité dans mon cas le : ou true ne marche pas !

En effet, je fais un truc du genre :

dd if="$inputFile" ibs=104 obs=4096 skip=1 | tee "$outputFile" | $command

La variable $command peut valoir md5sum ou "le truc qui fait rien".

Le problème est là que bash est trop rusé, il optimise !

Et donc si on fait

command="true"

Il se rend compte que la dernière partie de pipe (par laquelle il commence, faites un bash -x vous verrez !) n'a pas besoin de l'output qui précède et que son résultat est connu... et donc il ne fait pas les actions à l'intérieur du pipe !

Grrrr... c'est vraiment trop super optimisé ce truc.

Mais donc je me suis rabattu sur la solution 2 de totor avec

nop() {
  cat - >/dev/null
}

command="nop"

Du coup le dernier membre de la commande a besoin de l'input... pour le mettre à la poubelle !... mais bash n'est pas rusé au point de s'en rendre compte et du coup il fait bien toutes les commandes qui précèdent.

Et donc ça marche !

Dernière modification par Zakhar (Le 29/12/2010, à 20:57)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#6 Le 29/12/2010, à 21:43

ehmicky

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Dans ce cas, tes deux exigences du début :
- ne fait rien
- [Optionnel] qui copie tout ce qui arrive dans stdin vers stdout
sont en fait contradictoires, puisque "copier stdin vers stdout", c'est bien faire quelque chose, c'est précisément ce que fait cat sans arguments smile

Dernière modification par ehmicky (Le 29/12/2010, à 21:55)


Stego++, bibliothèque libre de stéganographie (avec cryptographie), à venir !
Besoin de votre aide :
Stats sur les compilateurs C++ les plus utilisés
Comment utiliser les archetypes C++ ?

Hors ligne

#7 Le 29/12/2010, à 22:04

Watael

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

franchement, il vaudrait mieux déterminer selon quels critères $command ne serait pas vide, et alors soit utiliser un if..then, ou un case..esac, genre

if [ "$critere" = ok ]
then
   dd if="$inputFile" ibs=104 obs=4096 skip=1 | tee "$outputFile" | md5sum
else
   dd if="$inputFile" ibs=104 obs=4096 skip=1 >"$outputFile"
fi

Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#8 Le 30/12/2010, à 10:10

Zakhar

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

@Watael : je suis d'accord avec toi si le cas se produit une seule fois. Cependant, dans mon cas, la chose étant répétée de nombreuses fois tout au long du programme, ça devient vite illisible avec une floppée de if partout. Ca multiplie aussi les risques d'erreur au développement et à la maintenance, car les lignes de commande étant passablement compliquées, il faut être sûr de bien les copier sans rien oublier, et en cas de modification de les avoir toutes modifiées.
Donc selon le cas, une méthode ou l'autre est plus appropriée.

Il existe aussi une méthode "intermédiaire" c'est de faire ça avec un eval. Mais au niveau performance je ne suis pas rassuré avec un eval (faudra que je teste ça) !


ehmicky : bah oui, tu as raison ! Mais tout ça vient du fait que bash est vraiment trop optimisé et il se rend compte que je lui met un truc qui fait rien et ne calcule même pas l'ouput des commandes précédentes !..
Mais si ça se trouve il y a un truc dans les paramètres du pipe (genre pipefail pour les erreurs) qui permet de forcer quand même à exécuter les commandes précédentes, ce qui m'éviterait le moche cat - /dev/null, juste pour faire calculer les commandes à bash !

P.S.: et pour le truc qui fait "rien" mais juste copie stdin sur stdout, j'utilise tee /dev/null, c'est juste que ça ne répond pas aux autres critères car tu ne peux pas mettre des arguments quelconques ! Mais en fait tu as raison, pour la dernière commande du pipe, je n'ai pas besoin de stdout lorsque je la remplace par "rien".

Dernière modification par Zakhar (Le 30/12/2010, à 10:16)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#9 Le 30/12/2010, à 11:11

Watael

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

les portions de codes qui se répétent devraient être dans une fonction, pour les raisons que tu donnes très justement.


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#10 Le 30/12/2010, à 11:22

kyncani

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Je ne crois pas que bash optimise quoi que ce soit, mais plutôt que :
- true fait son travail et termine. Il n'a pas besoin de lire sur stdin.
- tee voit son stdout invalide dès que true se termine (tout de suite donc), ne peut plus écrire de données et quitte avec une erreur.
- Idem pour dd, stdout invalide dès que tee se termine, ne peut plus écrire donc exit avec erreur

/home/kyncani/tmp/ > dd if=/dev/zero | tee a | true
/home/kyncani/tmp/ > echo ${PIPESTATUS[*]}
141 141 0
/home/kyncani/tmp/ >

Hors ligne

#11 Le 30/12/2010, à 13:23

Zakhar

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Bravo pour cette démonstration !..

Et y a-t-il un moyen de faire en sorte que le pipe attende la fin de toutes les commandes au lieu de se terminer prématurément ?

Mais dans un sens ma question est un peu illogique... le pipe sert à injecter une sortie dans une entrée et donc avec true ça n'a pas trop de sens.

Pour cela il faudrait alors remplacer le | (pipe) par un &&

Et du coup, le tee précédent ne sert plus et il faudrait remplacer le premier | par une redirection.

... et on a la solution de Watael !..

Watael a écrit :

les portions de codes qui se répétent devraient être dans une fonction, pour les raisons que tu donnes très justement.

Je me suis mal exprimé. C'est le "principe" qui se répète, c'est à dire des lignes de commande avec plusieurs pipes dont une partie peut être changée, mais les lignes en elle-mêmes sont toutes différentes.
Sinon bien évidemment, la fonction est la meilleure solution, j'en conviens !..


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#12 Le 30/12/2010, à 17:44

kyncani

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Ben je dirais que tu as les trois solutions déjà mentionnée :
- un "if", suivant que tu veux faire un md5sum ou pas
- un ">/dev/null", si la dernière commande du pipe sort des données
- un "| cat >/dev/null", si tu as absolument besoin d'une commande et non pas d'un pipe pour consommer les données
Après, à toi de voir suivant ton cas lequel tu préfères ou est le plus adapté.

Hors ligne

#13 Le 30/12/2010, à 20:26

Zakhar

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Plus la quatrième façon, puisque le besoin est de faire une commande ou une autre, d'utiliser : eval

Avec un truc du genre

eval "$PartieFixeDeLaCommande $PartieVariableDeLaCommande"

Et dans ce cas là, pour faire quelque chose ou pas on fait :

PartieVariableDeLaCommande="md5sum --status -c $TMP_FILE"

ou, pour ne rien faire

PartieVariableDeLaCommande=""

P.S.: dsl, j'ai pas révisé la syntaxe du eval récemment... c'est peut-être pas tout à fait correct. roll

Dernière modification par Zakhar (Le 30/12/2010, à 20:29)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#14 Le 31/12/2010, à 01:21

Totor

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

désolé, je n'ai pas eu le temps de mettre ma pierre à l'édifice dans la journée.
Voilà comment je procéderai :

En utilisant la logique d'une seule ligne dans les 2 cas, j'exploiterai les possibilités du bash donc sans utiliser cat (ni même eval où il faut faire attention au "quoting")

J'utiliserai donc la substitution de processus :
${command} < <(dd if="$inputFile" ibs=104 obs=4096 skip=1 | tee "$outputFile")

avec command=md5sum ou dans l'autre cas command="read"


-- Lucid Lynx --

Hors ligne

#15 Le 31/12/2010, à 01:35

TraGiKomiK

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Bonjour,

Alors je suis nul en bash (inconpetant meme tongue) mais en voyant ce post une idée tres bete m'est venu, qui est strictement en rapport avec le titre:


Inserer une variable vide, le tout est de savoir si ceci compte comme une commande tongue Car au final ca lance quelque une action mais aucun retour.


Desole si j'ai boulversé le bon deroulement de l'avancement du post big_smile [EDIT] qui ceci dit est marqué [RESOLU] lol

Dernière modification par TraGiKomiK (Le 31/12/2010, à 01:37)


Merci de mettre [RESOLU] dans le titre de votre post une fois le  probleme reglé!

GNU/Linux -> \o/

Hors ligne

#16 Le 31/12/2010, à 10:38

Zakhar

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

@TraGiKomiK : oui, c'est marqué "Résolu" parce que Totor m'a donnée une solution qui fonctionne parfaitement (la fonction interne qui ne fait rien)... mais ça n'empêche pas de trouver "mieux" !.. (on est un peu puristes)

@Totor : cool ta solution avec substitution de processus. J'ai lu ce passage dans la doc, mais pas encore totalement compris les arcanes de cette subtilité de bash. C'est l'occasion de m'y pencher de plus près. Faut aussi que je regarde la doc de "read", parce que là il va avaler du fichier binaire... pas sûr que ça lui plaise !
[Edit] Effectivement, le manpage d'Ubuntu précise :

man read a écrit :

STDIN

       The standard input shall be a text file.

... or ce n'est pas le cas !

Dernière modification par Zakhar (Le 31/12/2010, à 10:47)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#17 Le 31/12/2010, à 10:53

ehmicky

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

kyncani a écrit :

Je ne crois pas que bash optimise quoi que ce soit, mais plutôt que :
- true fait son travail et termine. Il n'a pas besoin de lire sur stdin.
- tee voit son stdout invalide dès que true se termine (tout de suite donc), ne peut plus écrire de données et quitte avec une erreur.
- Idem pour dd, stdout invalide dès que tee se termine, ne peut plus écrire donc exit avec erreur

/home/kyncani/tmp/ > dd if=/dev/zero | tee a | true
/home/kyncani/tmp/ > echo ${PIPESTATUS[*]}
141 141 0
/home/kyncani/tmp/ >

Moi non plus, je pense pas du tout qu'il s'agisse d'un problème d'optimisation mais juste de redirection de stdin.

Zakhar a écrit :

@TraGiKomiK@Totor : cool ta solution avec substitution de processus. J'ai lu ce passage dans la doc, mais pas encore totalement compris les arcanes de cette subtilité de bash. C'est l'occasion de m'y pencher de plus près. Faut aussi que je regarde la doc de "read", parce que là il va avaler du fichier binaire... pas sûr que ça lui plaise !
[Edit] Effectivement, le manpage d'Ubuntu précise :

man read a écrit :

STDIN

       The standard input shall be a text file.

... or ce n'est pas le cas !

Unix ne fait pas de distinction théorique entre fichier binaire et fichier texte (même si on peut en faire d'un point de vue pratique, la plupart des commandes s'en fichent). La distinction est pertinente que dans les systèmes qui ont des newlines multi-octets, comme Windows.

Dernière modification par ehmicky (Le 31/12/2010, à 10:59)


Stego++, bibliothèque libre de stéganographie (avec cryptographie), à venir !
Besoin de votre aide :
Stats sur les compilateurs C++ les plus utilisés
Comment utiliser les archetypes C++ ?

Hors ligne

#18 Le 31/12/2010, à 11:34

Totor

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

ehmicky a écrit :
Zakhar a écrit :
man read a écrit :

STDIN
       The standard input shall be a text file.

... or ce n'est pas le cas !

Unix ne fait pas de distinction théorique entre fichier binaire et fichier texte (même si on peut en faire d'un point de vue pratique, la plupart des commandes s'en fichent). La distinction est pertinente que dans les systèmes qui ont des newlines multi-octets, comme Windows.

oui, aucun pb d'utiliser read avec un fichier binaire.

sinon, après réflexion, nul besoin d'utiliser la substitution de processus, un pipeline classique suffit (avec read en tant que commande qui ne fait rien).
je ne sais plus pourquoi je suis passé par la substitution de processus roll

Cela dit, je rejoins Watael, le plus compréhensible et le plus facilement maintenable serait d'utiliser une classique structure de contrôle.


-- Lucid Lynx --

Hors ligne

#19 Le 31/12/2010, à 14:32

Zakhar

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Alors mes questions concernent ce script : tuXtremMerge

Je ne vois pas trop bien l'avantage du "process substitution", après avoir lu et relu la doc, dans la mesure où "vu de l'extérieur", c'est une seule commande qui se déverse dans le MD5 (même si en réalité c'est deux commandes pipées)

Par contre en lisant la documentation, je suis tombé sur :

coproc

Et ça je pense que c'est bigrement intéressant pour régler le sort du tee dans le cas où il est inutile.

Extrait de code :

if [ $OPTION_m ]; then
 DEST_FILE_NAME_PART="/dev/null"
fi

cat "$this_file_radix.xtm" 2>/dev/null | tee -a "$DEST_FILE_NAME_PART" | $MD5_PROG --status -c "$TMP_FILE"

Donc si on ne spécifie pas l'option "m", le tee joue son rôle normal :
- Le fichier source (ici "$this_file_radix.xtm") est lu
- Il est rajouté (option -a de tee) au fichier "$DEST_FILE_NAME_PART" (qui désigne vraiment un fichier réel)
- puis le tee "pipe" le contenu du fichier source reçu vers MD5 pour calculer la somme de contrôle.

(ensuite un test, non recopié dans l'extrait, vérifie que tout s'est bien passé)

Si on spécifie l'option "-m", plutôt que de faire des if (la ligne ci-dessus est répétée plusieurs fois, et l'option m n'est pas la seule), on se contente de spécifier que le fichier de sortie est /dev/null
- La même commande fonctionne toujours
- Mais le bout avec le tee devient complètement inutile et fait des copies d'octets d'un endroit à un autre pour rien !..
... d'ailleurs on peut même dans ce cas retirer le "pipe" en faisant lire directement le fichier à md5sum ! (mais ça c'est la solution "eval")

L'idée serait alors d'utiliser un "coproc" avec le tee à "intercaler" ou pas (selon option m) dans le pipe.

Et on peut aussi certainement faire un "coproc" également avec le md5sum...

Après tout coproc n'est ni plus ni moins que ce que fait le pipe de façon transparente, rendu visible à l'utilisateur.

Je vais explorer cette voie... j'adore l'asynchronisme depuis que j'ai été élevé au biberon avec CTOS, O.S. génialissime mort par erreur commerciale de son créateur (Burroughs, Unisys).

Dernière modification par Zakhar (Le 31/12/2010, à 14:39)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#20 Le 31/12/2010, à 15:21

Totor

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

les avantages de la substitution de processus :
- tout est exécuté dans le même environnement. il n'y a donc pas de perte d'information (les variables conservent leur valeur modifiée durant l'execution du pipeline)
pour ex, test ce script :

toto=1
{ toto=2; echo "${toto}"; } | >/dev/null
echo ${toto}
{ toto=2; echo "${toto}"; } > >( >/dev/null)
echo ${toto}

- plus rapide car pas de duplication d'environnement
- pas besoin de créer des fichiers "temporaire" dans certains cas :

ex : trier 2 fichiers après avoir sélectionner que quelques lignes des dits fichiers --> sort <(grep toto fichier1) <(grep titi fichier2)

plutôt que : grep toto fichier1 > _f1; grep titi fichier2 > _f2; sort _f1 _f2 && rm _f1 _f2

sinon, il n'y a vraiment aucun intérêt à utiliser un coproc.

aussi : tu es l'heureux élu d'un golden award useless of cat
cat "$this_file_radix.xtm" 2>/dev/null | tee -a "$DEST_FILE_NAME_PART"
Voilà qui est bien plus propre : tee -a "$DEST_FILE_NAME_PART" < "$this_file_radix.xtm"

Dernière modification par Totor (Le 31/12/2010, à 15:21)


-- Lucid Lynx --

Hors ligne

#21 Le 31/12/2010, à 16:04

Zakhar

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Je commence à comprendre !..

Je pense que le "process substitution" va pouvoir me servir utilement dans le cas présent pour :

tee -a "$DEST_FILE_NAME_PART" <"$this_file_radix.xtm" | $MD5_PROG --status -c "$TMP_FILE"

(J'ai déjà modifié la ligne car je suis bon jouer, et je remets en jeu mon"Award" !)

Je ne savais bien comment donner à md5sum son fichier où il lit le MD5 pour faire son "status".
Donc un peu plus haut dans le programme on fait :

echo "$this_file_MD5 *-" >"$TMP_FILE"

Si je suis ton raisonnement, au lieu de passer bêtement par un fichier temporaire je dois pouvoir donc faire :

tee -a "$DEST_FILE_NAME_PART" <"$this_file_radix.xtm" | $MD5_PROG --status -c <(echo "$this_file_MD5 *-")

où bien est-ce que cette substitution va tout casser parce que md5sum ne lira plus le stdin qui lui a été "pipé" ?..
(J'ai pas mon Ubuntu sous la main pour essayer là !)

Quand à la non duplication des variables d'environnement c'est bigrement intéressant pour la suite de mes développements : Zenity

En effet, le fonctionnement standard de la jauge est le suivant :

(
# liste d'instructions
echo "# Message" # pour changer le message
echo "25" # nombres pour changer le pourcentage
# liste d'instructions
) | zenity --progress

Et donc le bloc d'instruction dont tu surveilles la progression est un sub-shell. Ce qu'il veut dire que si tu as besoin de passer des valeurs calculées à l'intérieur de ce bloc vers la suite du script... beh... t'es coincé... sauf à les mettre dans un fichier (c'est moche !).
Je présume que dans ce cas là, le process-substitution est la solution !

Et ça donnerait donc

(
# liste d'instructions
echo "# Message" # pour changer le message
echo "25" # nombres pour changer le pourcentage
# liste d'instructions
var="123"
) > >( zenity --progress)

echo "var=$var"

Dernière modification par Zakhar (Le 31/12/2010, à 16:08)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#22 Le 31/12/2010, à 16:07

Totor

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

t'as tout bon !


-- Lucid Lynx --

Hors ligne

#23 Le 31/12/2010, à 16:10

Zakhar

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

Bon... ben j'ai du test à faire ce soir ! wink

Et merci Totor pour avoir fait avancer ma connaissance du bash !

P.S.: et donc puis-je aussi remplacer ma fonction

nop()
{
 cat - >/dev/null
}

par

nop()
{
 >/dev/null
}

... histoire d'éviter un deuxième award !

Dernière modification par Zakhar (Le 31/12/2010, à 16:22)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#24 Le 31/12/2010, à 16:21

Totor

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

de rien...
une fois que tu auras finaliser... je serais heureux de te montrer un truc avec zenity et la barre de progression wink


-- Lucid Lynx --

Hors ligne

#25 Le 31/12/2010, à 16:23

Zakhar

Re : [Résolu] Existe-t-il une commande qui ne fait rien ?

The secret features of Zenity progress bar by Totor Unlimited ! big_smile tongue

Dernière modification par Zakhar (Le 31/12/2010, à 16:24)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne