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 les fichiers vidéo Jusqu'à YouTube en utilisant GoogleCL .

Comme je fais ce téléchargement dans une 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) affiche une chaîne qui me dit si le téléchargement a réussi ou non.

Mais je ne sais pas comment rediriger ça "return string" dans une variable pour vérifier les succès.

C'est 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
demandé sur einpoklum 2011-04-18 14:38:04

7 réponses

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

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 veut évaluer une expression entre crochets, ce n'est pas vrai, si prend toujours une commande et vérifie l'état de l'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 un raccourci optimisé pour le faire aller plus vite dans bash, mais conceptuellement c'est toujours vrai).

La capture de la sortie se fait via des backticks, comme ceci

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.

modifier: Vous avez une drôle si chose dans votre fonction.. Je n'ai pas remarqué au début, mais cela peut être évité si vous activez l'option shell nullglob (cela fera que ./*.mov s'étendra à la chaîne vide, s'il n'y en a pas fichier). En outre, citez 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
répondu falstro 2011-04-18 11:03:33

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 erreurs) et une valeur différente indique un code d'erreur.

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 de une commande simple est son état de sortie, ou 128 + n Si le la commande est terminée par le signal n.

Et:

Retour [n]
Provoque la sortie d'une fonction avec la valeur de retour spécifiée par n. Si n est omis, le retour le statut est celui du dernier commande exécutée dans le corps de la fonction. Si utilisé en dehors d'un la fonction, mais lors de l'exécution d'un script par le . (source) de commande, le shell pour arrêter l'exécution de ce script et renvoie n ou l'état de sortie de la dernière commande exécuté dans le script comme état de sortie du script. Si utilisé en dehors d'une fonction et pas pendant l'exécution d'un script par . le retour d'état est faux. Toute commande associé au piège de retour est exécuté avant l'exécution reprend 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 la signification 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 y a deux formes:

          $(command)
   or
          `command`

Bash effectue l'expansion en exécutant la commande et en remplaçant la substitution de commande par la norme sortie de la commande, avec tous les retours à la ligne de fin supprimés. Retours à la ligne intégrés ne sont pas supprimés, mais ils peuvent être supprimé pendant le fractionnement des mots. La commande substitution $(fichier cat) peut être remplacée par équivalent mais plus rapide $(

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

La Barre oblique inverse conserve sa signification littérale sauf lorsqu'il est suivi par $, `, ou . Le premier backquote Non précédé d'une barre oblique inverse termine le substitution de commande. Lors de l'utilisation de la formulaire $(commande) , tous les caractères entre parenthèses composent la commande; aucun sont traités spécialement.

   Command substitutions may be nested.  To nest when using the

Backquoted forme, échapper à l'intérieur backquotes avec des barres obliques inverses.

Si la substitution apparaît entre guillemets, fractionnement de mots et l'expansion pathname ne sont pas effectuée sur les résultats.

4
répondu user unknown 2011-04-18 11:03:26

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

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

S'il s'avère que le code de 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 met stderr sur le fd stdout, avant de rediriger stdout vers rien.

2
répondu Douglas Leeder 2011-04-18 10:44:20

Utiliser $()

variable=$(google youtube post --access unlisted --category Tech $f )
2
répondu kurumi 2011-04-18 14:14:17

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

CONTENT=`google youtube post --access unlisted --category Tech $f > /dev/null`
0
répondu Nick 2011-04-18 10:43:15

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") print $2}'|\
while read i ; do\
    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'|\
    tail -2|\
    head -1)
    echo "$url_current" >> ~/temp/youtube_top1.txt
done 
0
répondu lamasnik 2011-11-01 19:46:30

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

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

Avertissement: Ceci est une réponse en double

Voici comment vous le faites...

Commande:

# 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 il est important:

  1. supposons que le series | of | commands est une série très compliquée de commandes canalisées.
  2. mystic_command est peut accepter stdin que le fichier, mais pas l'option arg donc doit venir comme une 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 une parenthèse n'est pas nécessaire mais le fait couler comme un tuyau continu comme si les 2 commandes étaient dans un fichier de script séparé.

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

mystic_command --opt "$(series | of | commands)" /path/to/file | handle_mystified_file
0
répondu Bruno Bronosky 2017-05-23 12:33:59