bash 想要通过将其输出重定向到变量来检查命令是否成功
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5701653/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Want to check whether a command succeeded by redirecting its output to a variable
提问by Patrick
I'm currently writing a bash script which loads video files up to to YouTube using GoogleCL.
我目前正在编写一个 bash 脚本,它使用GoogleCL将视频文件加载到 YouTube 。
As I'm doing this uploading stuff in a loop (because there can be multiple video files) I would like to check if each file had been uploaded successfully before I upload the next one.
由于我正在循环上传内容(因为可能有多个视频文件),我想在上传下一个文件之前检查每个文件是否已成功上传。
The command google youtube post --access unlisted --category Tech $f
(where $f represents the file) outputs a string which tells me whether the upload has been successful or not.
该命令google youtube post --access unlisted --category Tech $f
(其中 $f 代表文件)输出一个字符串,告诉我上传是否成功。
But I don't know how to redirect that "return string" into a variable to do check the successs.
但我不知道如何将该“返回字符串”重定向到一个变量中以检查是否成功。
That's what I have:
这就是我所拥有的:
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
Can anybody help me?
有谁能够帮助我?
采纳答案by falstro
My guess is that you could depend on the error code from the google command as well (I'm assuming it returns error if it failed to upload, but you should probably double check this).
我的猜测是,您也可以依赖 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
A common misconception is that if wants a bracketed expression to evaluate, this is not true, if always takes a command and checks the error status; usually this command is [
which is an alias for test
, which evaluates the expression. (And yes, I'd be surprised if there isn't an optimized shortcut to make it go faster inside bash, but conceptually it's still true).
一个常见的误解是,如果想要一个括号表达式来计算,这是不正确的,如果总是接受一个命令并检查错误状态;通常这个命令是[
which 的别名test
,它计算表达式。(是的,如果没有优化的快捷方式来使其在 bash 中运行得更快,我会感到惊讶,但从概念上讲,它仍然是正确的)。
Capturing output is done via backticks, like so
捕获输出是通过反引号完成的,就像这样
result=`command argument a b c`
or using $()
或使用 $()
result=$(command argument a b c)
but it's probably better to use the error code in this case.
但在这种情况下最好使用错误代码。
EDIT:You have a funny if thing in your function.. I didn't notice at first, but it can be avoided if you enable nullglob
shell option (this will make ./*.mov
to expand to the empty string, if there are no files). Also, quote that $f
or it'll break if your file names contain spaces
编辑:如果你的函数中有一个有趣的事情..我一开始没有注意到,但是如果你启用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.
哈。
回答by user unknown
I would call it, The command ... outputs a string
. 'Return' is a keyword, and the return value is a number, where 0 means by convention success (0 errors) and a different value indicates an error code.
我会称之为,The command ... outputs a string
。' Return' 是一个关键字,返回值是一个数字,其中 0 表示约定成功(0 错误),不同的值表示错误代码。
You grab the output by:
您可以通过以下方式获取输出:
result=$(google youtube post --access unlisted --category Tech $f)
but will often see the inferior solution:
但经常会看到次等的解决方案:
result=`cmd param1 param2`
inferior, because backticks are easily confused with apostrophes (depending on the font) and hard to nest, so don't use them.
劣等,因为反引号很容易与撇号混淆(取决于字体)并且难以嵌套,所以不要使用它们。
From 'man bash':
来自“男人的狂欢”:
The return value of a simple command is its exit status, or 128+n if the command is terminated by signal n.
简单命令的返回值是它的退出状态,如果命令被信号 n 终止,则返回 128+n。
and:
和:
return [n]
Causes a function to exit with the return value specified by n. If n is omitted, the return status is that of the last command executed in the function body. If used outside a function, but during execution of a script by the . (source) command, it causes the shell to stop executing that script and return either n or the exit status of the last command executed within the script as the exit status of the script. If used outside a function and not during execution of a script by ., the return status is false. Any command associated with the RETURN trap is executed before execution resumes after the function or script.
return [n]
使函数以 n 指定的返回值退出。如果省略 n,则返回状态为函数体中执行的最后一个命令的状态。如果在函数外部使用,但在由 . (source) 命令,它会导致 shell 停止执行该脚本并返回 n 或脚本中执行的最后一个命令的退出状态作为脚本的退出状态。如果在函数外部使用而不是在脚本执行期间使用 .,则返回状态为 false。与 RETURN 陷阱关联的任何命令都会在函数或脚本之后恢复执行之前执行。
The return value/exit code of the last command is gained through $?.
最后一条命令的返回值/退出代码通过 $? 获得。
The keyword for the meaning you meant is command substitution. Again 'man bash':
您的意思的关键字是命令替换。再次“男人猛击”:
Command Substitution
Command substitution allows the output of a command to replace the command name. There are two forms:$(command) or `command`
Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted. Embedded newlines are not deleted, but they may be removed during word splitting. The command substitution $(cat file) can be replaced by the equivalent but faster $(< file).
When the old-style backquote form of substitution is used,
backslash retains its literal meaning except when followed by $, `, or . The first backquote not preceded by a backslash terminates the command substitution. When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.
Command substitutions may be nested. To nest when using the
backquoted form, escape the inner backquotes with backslashes.
If the substitution appears within double quotes, word splitting and pathname expansion are not performed on the results.
命令替换
命令替换允许命令的输出来替换命令名称。有两种形式:$(command) or `command`
Bash 通过执行命令并用命令的标准输出替换命令替换来执行扩展,并删除任何尾随的换行符。嵌入的换行符不会被删除,但在分词过程中可能会被删除。命令替换 $(cat file) 可以替换为等效但速度更快的 $(< file)。
When the old-style backquote form of substitution is used,
反斜杠保留其字面含义,除非后跟 $、` 或 。前面没有反斜杠的第一个反引号终止命令替换。使用 $(command) 形式时,括号之间的所有字符组成命令;没有被特殊对待。
Command substitutions may be nested. To nest when using the
反引号形式,用反斜杠转义内部反引号。
如果替换出现在双引号内,则不会对结果执行分词和路径名扩展。
回答by Douglas Leeder
If you are still getting output after > /dev/null
then it's coming out on stderr, so standard backticks or $()
won't work.
如果之后您仍然获得输出,> /dev/null
则它会在 stderr 上出现,因此标准反引号或$()
将不起作用。
First, see if the return code indicates a problem: Examine $? after success and failure.
首先,查看返回码是否表明存在问题:检查 $? 在成功和失败之后。
If it turns out the return code isn't sufficent, you can redirect the output:
如果结果返回代码不够,您可以重定向输出:
RETURNVALUE=$(google youtube post --access unlisted --category Tech $f 2>&1 >/dev/null)
2>&1
puts stderr on the stdout fd, before you redirect stdout to nothing.
2>&1
在将 stdout 重定向到空之前,将 stderr 放在 stdout fd 上。
回答by kurumi
Use $()
用 $()
variable=$(google youtube post --access unlisted --category Tech $f )
回答by Nick
You can assign it to a variable by using backticks:
您可以使用反引号将其分配给变量:
CONTENT=`google youtube post --access unlisted --category Tech $f > /dev/null`
回答by lamasnik
Example for access youtube
访问 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") print }'|\ while read i ; do\ page_youtube=`curl -s "http://www.youtube.com/${i}"`;\ echo `echo -e "$page_youtube" |awk '{if ( ~ "") start=1; if ( ~ "") start=0; if (start == 1) print}'|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 }'|\ sed 's/;$//g'|\ sed 's/\u.*//g'|\ tail -2|\ head -1) echo "$url_current" >> ~/temp/youtube_top1.txt done# 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
回答by Bruno Bronosky
The answer to the question is to use the read
command.
问题的答案是使用read
命令。
Sure all these other answers show ways to not do what the OP asked, but that really screws up the rest of us who searched for the OP's question.
当然,所有这些其他答案都显示了不做 OP 要求的方法,但这确实让我们其他搜索 OP 问题的人搞砸了。
Disclaimer: This is a duplicate answer
免责声明:这是一个重复的答案
Here is how you do it...
这是你如何做到的...
Command:
命令:
mystic_command --opt "$(series | of | commands)" /path/to/file | handle_mystified_file
Here is what it is doing and why it is important:
这是它正在做什么以及为什么它很重要:
- Let's pretend that the
series | of | commands
is a very complicated series of piped commands. mystic_command
is could accept stdin as the file, but not the option argtherefore it must come in as a variable**read
takes stdin and places it into the variable$string
- Putting the
read
and themystic_command
into a "sub shell" via parenthesis is not necessary but makes it flow like a continuous pipe as if the 2 commands where in a separate script file.
- 让我们假设这
series | of | commands
是一系列非常复杂的管道命令。 mystic_command
is 可以接受 stdin 作为文件,但不能接受选项 arg因此它必须作为变量进来**read
获取 stdin 并将其放入变量中$string
- 不需要通过括号将
read
和mystic_command
放入“子外壳”中,但使其像连续管道一样流动,就好像 2 个命令位于单独的脚本文件中一样。
**There is always an alternative, and in this case the alternative is ugly and unreadable:
**总有一个替代方案,在这种情况下,替代方案是丑陋且不可读的:
##代码##