web-dev-qa-db-fra.com

Vous voulez vérifier si une commande a réussi en redirigeant sa sortie vers une variable

J'écris actuellement un script bash qui charge des fichiers vidéo sur YouTube en utilisant GoogleCL .

Comme je fais ce téléchargement en boucle (car il peut y avoir plusieurs fichiers vidéo), je voudrais vérifier si chaque fichier a été téléchargé avec succès avant de télécharger le suivant.

La commande google youtube post --access unlisted --category Tech $f (où $ f représente le fichier) génère une chaîne qui me dit si le téléchargement a réussi ou non.

Mais je ne sais pas comment rediriger cette "chaîne de retour" dans une variable pour vérifier les succès.

Voilà ce que j'ai:

for f in ./*.ogv ./*.mov ./*.mp4
do
    if [[ '*' != ${f:2:1} ]]
    then
        echo "Uploading video file $f"

        # How to put the return value of the following command into a variable?
        google youtube post --access unlisted --category Tech $f > /dev/null

        # Now I assume that the output of the command above is available in the variable RETURNVALUE
        if [[ $RETURNVALUE == *uploaded* ]]
        then
            echo "Upload successful."
        else
            echo "Upload failed."
        fi
    fi
done

Quelqu'un peut-il m'aider?

23
Patrick

Je suppose que vous pouvez également dépendre du code d'erreur de la commande google (je suppose qu'il renvoie une erreur s'il n'a pas été téléchargé, mais vous devriez probablement vérifier cela à nouveau).

for f in ./*.ogv ./*.mov ./*.mp4; do
  if [[ '*' != ${f:2:1} ]]; then

    echo "Uploading video file $f"
    if google youtube post --access unlisted --category Tech "$f" > /dev/null
    then
      echo "Upload successful."
    else
      echo "Upload failed."
    fi

  fi
done

Une idée fausse commune est que si l'on veut qu'une expression entre crochets soit évaluée, ce n'est pas vrai, si elle prend toujours une commande et vérifie l'état d'erreur; généralement cette commande est [ qui est un alias pour test, qui évalue l'expression. (Et oui, je serais surpris s'il n'y a pas de raccourci optimisé pour le rendre plus rapide dans bash, mais conceptuellement, c'est toujours vrai).

La capture de sortie se fait via des backticks, comme ça

result=`command argument a b c`

ou en utilisant $()

result=$(command argument a b c)

mais il est probablement préférable d'utiliser le code d'erreur dans ce cas.

ÉDITER: Vous avez une drôle de chose si dans votre fonction .. Je ne l'ai pas remarqué au début, mais cela peut être évité si vous activez l'option nullglob Shell (cela fera ./*.mov Se développer à vide s'il n'y a pas de fichiers). Notez également que $f Ou il se cassera si vos noms de fichiers contiennent des espaces

shopt -s nullglob
for f in ./*.ogv ./*.mov ./*.mp4; do
  echo "Uploading video file $f"
  if google youtube post --access unlisted --category Tech "$f" > /dev/null
  then
    echo "Upload successful."
  else
    echo "Upload failed."
  fi
done

HTH.

21
falstro

Je l'appellerais, The command ... outputs a string. ' Return ' est un mot-clé, et la valeur de retour est un nombre, où 0 signifie par convention succès (0 erreur) et une valeur différente indique une erreur code.

Vous saisissez la sortie par:

result=$(google youtube post --access unlisted --category Tech $f)

mais verra souvent la solution inférieure:

result=`cmd param1 param2`

inférieur, car les backticks sont facilement confondus avec les apostrophes (selon la police) et difficiles à imbriquer, alors ne les utilisez pas.

De 'man bash':

La valeur de retour d'une commande simple est son état de sortie, ou 128 + n si la commande est terminée par le signal n.

et:

retourner [n]
Provoque la fermeture d'une fonction avec la valeur de retour spécifiée par n. Si n est omis, l'état de retour est celui de la dernière commande exécutée dans le corps de la fonction. Si utilisé en dehors d'une fonction, mais pendant l'exécution d'un script par le. (source), elle oblige le shell à arrêter l'exécution de ce script et renvoie soit n, soit l'état de sortie de la dernière commande exécutée dans le script comme état de sortie du script. S'il est utilisé en dehors d'une fonction et non pendant l'exécution d'un script par., Le statut de retour est faux. Toute commande associée à l'interruption RETURN est exécutée avant la reprise de l'exécution après la fonction ou le script.

La valeur de retour/code de sortie de la dernière commande est obtenue via $ ?.

Le mot-clé pour le sens que vous vouliez dire est substitution de commande. Encore une fois 'man bash':

Substitution de commande
La substitution de commande permet à la sortie d'une commande de remplacer le nom de la commande. Il existe deux formes:

          $(command)
   or
          `command`

Bash effectue l'expansion en exécutant la commande et en remplaçant la substitution de commande par la sortie standard de la commande, avec tous les retours à la ligne supprimés. Les sauts de ligne incorporés ne sont pas supprimés, mais ils peuvent être supprimés lors du fractionnement de Word. La substitution de commande $ (fichier cat) peut être remplacée par l'équivalent mais plus rapide $ (<fichier).

   When  the old-style backquote form of substitution is used,

la barre oblique inverse conserve sa signification littérale, sauf lorsqu'elle est suivie de $, `ou. La première citation inverse non précédée d'une barre oblique inverse met fin à la substitution de commande. Lors de l'utilisation du formulaire $ (commande), tous les caractères entre parenthèses constituent la commande; aucun n'est traité spécialement.

   Command substitutions may be nested.  To nest when using the

forme entre guillemets, échappez aux guillemets intérieurs avec des barres obliques inverses.

Si la substitution apparaît entre guillemets doubles, le fractionnement de Word et l'expansion du nom de chemin ne sont pas effectués sur les résultats.

4
user unknown

Utilisez $()

variable=$(google youtube post --access unlisted --category Tech $f )
2
kurumi

Si vous obtenez toujours une sortie après > /dev/null, Cela sort sur stderr, donc les backticks standard ou $() ne fonctionneront pas.

Tout d'abord, voyez si le code retour indique un problème: Examinez $? après le succès et l'échec.

S'il s'avère que le code retour n'est pas suffisant, vous pouvez rediriger la sortie:

RETURNVALUE=$(google youtube post --access unlisted --category Tech $f 2>&1 >/dev/null)

2>&1 Place stderr sur le fd stdout, avant de rediriger stdout vers rien.

2
Douglas Leeder

Vous pouvez l'affecter à une variable à l'aide de backticks:

CONTENT=`google youtube post --access unlisted --category Tech $f > /dev/null`
0
Nick

Exemple d'accès à YouTube

 rm ~/temp/youtube_top_title1.txt 
 rm ~/temp/youtube_top1.txt 
 curl "http://www.youtube.com/"|\
 grep -o 'watch [^ "] *' |\
 sort -n |\
 uniq -c |\
 awk '{if ($ 1! =" 1 " ) imprimer $ 2} '|\
 pendant la lecture i; faire\
 page_youtube = `curl -s" http://www.youtube.com/${i} "`;\
 echo `echo -e" $ page_youtube "| awk '{if ($ 1 ~" ") start = 1; if ($ 1 ~" ") start = 0; if (start == 1) print $ 0}' | grep -v '' `>> ~/temp/youtube_top_title1.txt 
 url_current = $ (echo -e" $ page_youtube "|\
 grep -o" url = [^,] *, "|\
 sed 's/url = // g; s /, // g' |\
 php -r '$ f = fopen (" php: // stdin "," r "); while (FALSE! == ($ line = fgets ($ f))) echo urldecode ($ line); '|\
 awk' {print $ 1} '|\
 sed 's /; $ // g' |\
 sed 's/\\ u. * // g' |\
 queue -2 |\
 tête -1 ) 
 echo "$ url_current" >> ~/temp/youtube_top1.txt 
 done 
0
lamasnik

La réponse à la question est d'utiliser la commande read.

Bien sûr, toutes ces autres réponses montrent des façons de ne pas faire ce que le PO a demandé, mais cela décourage vraiment le reste d'entre nous qui ont cherché la question du PO.

Avertissement: Ceci est une réponse en double

Voici comment vous le faites ...

Commander:

# I would usually do this on one line, but for readability...
series | of | commands \
| \
(
  read string;
  mystic_command --opt "$string" /path/to/file
) \
| \
handle_mystified_file

Voici ce qu'il fait et pourquoi c'est important:

  1. Imaginons que le series | of | commands est une série très complexe de commandes piped.
  2. mystic_command est peut accepter stdin comme fichier, mais pas l'option arg donc il doit entrer comme variable **
  3. read prend stdin et le place dans la variable $string
  4. Mettre le read et le mystic_command dans un "sous-shell" via des parenthèses n'est pas nécessaire mais le fait couler comme un canal continu comme si les 2 commandes se trouvaient dans un fichier de script séparé.

** Il y a toujours une alternative, et dans ce cas, l'alternative est moche et illisible:

mystic_command --opt "$(series | of | commands)" /path/to/file | handle_mystified_file
0
Bruno Bronosky