想要通过将其输出重定向到变量来检查命令是否成功

时间:2011-04-18 10:38:04

标签: bash return-value variable-assignment

我目前正在编写一个bash脚本,使用GoogleCL将视频文件加载到YouTube。

由于我在循环中上传内容(因为可能有多个视频文件),我想检查每个文件是否已成功上传,然后再上传下一个文件。

命令google youtube post --access unlisted --category Tech $f(其中$ f代表文件)输出一个字符串,告诉我上传是否成功。

但我不知道如何将“返回字符串”重定向到变量中以检查成功。

这就是我所拥有的:

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

有人能帮助我吗?

7 个答案:

答案 0 :(得分:21)

我的猜测是你可以依赖google命令的错误代码(我假设如果上传失败就会返回错误,但你应该仔细检查一下)。

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

一个常见的误解是,如果想要一个括号括起来的表达式来评估,如果总是接受一个命令并检查错误状态,那就不是这样;通常此命令是[,它是test的别名,用于计算表达式。 (是的,如果没有一个优化的快捷方式让它在bash中变得更快,我会感到惊讶,但从概念上讲它仍然是真的。)

捕获输出是通过反引号完成的,如此

result=`command argument a b c`

或使用$()

result=$(command argument a b c)

但在这种情况下使用错误代码可能更好。

修改: 你的函数中有一个有趣的东西......起初我没有注意到,但如果启用nullglob shell选项可以避免这种情况(这会使./*.mov扩展为空字符串,如果没有文件)。另外,如果您的文件名包含空格,则引用$f或它会中断

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。

答案 1 :(得分:4)

我会称之为The command ... outputs a string。 ' Return '是一个关键字,返回值是一个数字,其中0表示按惯例成功(0个错误),不同的值表示错误代码。

您可以通过以下方式获取输出:

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

但经常会看到劣质解决方案:

result=`cmd param1 param2`

低级,因为反叛很容易与撇号混淆(取决于字体)并且难以嵌套,所以不要使用它们。

来自'man bash':

  

简单命令的返回值   是退出状态,如果是,则为128 + n   命令由信号n终止。

  

返回[n]
    使函数以指定的返回值退出   由n。如果省略n,则返回   状态是最后一个                 在函数体中执行的命令。如果在外面使用   功能,但在执行期间   脚本由。 (资源)                 命令,它导致shell停止执行该脚本   并返回n或退出状态   最后一个命令                 在脚本中执行作为退出状态   脚本。如果在功能之外使用   而不是在执行期间                 脚本by。,返回状态为false。任何命令   与RETURN陷阱相关联的是   执行前执行                 在函数或脚本之后继续。

最后一个命令的返回值/退出代码是通过$?获得的。

您指的含义的关键字是命令替换。再次'man bash':

  

命令替换
    命令替换允许输出命令来替换   命令名称。有两种形式:

          $(command)
   or
          `command`
     

Bash通过执行命令并用标准替换命令替换来执行扩展   输出命令,删除任何尾随换行符。嵌入式换行   不会被删除,但它们可能会被删除   在分词时删除。          命令替换$(cat文件)可以替换为   相当但更快的$(< file)。

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

反斜杠保留了它的字面含义   除了后跟$,`,          要么 。没有反斜杠的第一个反引号终止了   命令替换。使用时   $(命令)表格,          括号之间的所有字符组成命令;没有   特别对待。

   Command substitutions may be nested.  To nest when using the
     反引形式,逃避内心   带反斜杠的反引号。

     

如果替换出现在双引号内,则单词拆分   和路径名扩展不是   对结果进行了表达。

答案 2 :(得分:2)

使用$()

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

答案 3 :(得分:2)

如果你仍然在> /dev/null之后获得输出,那么它就会出现在stderr上,所以标准的反引号或$()将不起作用。

首先,查看返回码是否表示存在问题:检查$?成功与失败之后。

如果事实证明返回代码不够,您可以重定向输出:

RETURNVALUE=$(google youtube post --access unlisted --category Tech $f 2>&1 >/dev/null)
在将stdout重定向到空之前,

2>&1将stderr置于stdout fd上。

答案 4 :(得分:0)

您可以使用反引号将其指定给变量:

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

答案 5 :(得分:0)

访问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 

答案 6 :(得分:0)

问题的答案是使用read命令。

当然,所有这些其他答案都显示了不做OP所要求的方法,但这确实搞砸了我们其他寻找OP问题的人。

免责声明:This is a duplicate answer

以下是你的表现......

命令:

# 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

这是它正在做什么以及为什么它很重要:

  1. 让我们假装series | of | commands是一系列非常复杂的管道命令。
  2. mystic_command可以接受stdin作为文件,但不是选项arg 因此必须作为变量**
  3. read接受stdin并将其放入变量$string
  4. 不需要通过括号将readmystic_command放入“子shell”中,但会使其像连续管道一样流动,就好像2个命令位于单独的脚本文件中一样。
  5. ** 总有另一种选择,在这种情况下,替代方案是丑陋且难以理解的:

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