我的目的是在下载文件时抓取(然后修改)cURL输出。
curl -# -L --user-agent 'Mozilla/5.0' -o "`echo -e "$filename"`" "$url" 2>&1 |
while true
do
read <&1 line1 line2
echo $line2
if [ "`echo $line2 | grep -o "#"`" = "#" ] ; then
echo "downloading..."
break
elif [ "`echo $line2 | grep -o "curl"`" = "curl" ] ; then
echo $line2
break
else
echo "stderr still empty"
fi
done
问题是cURL输出(发送到stderr)是动态的,所以我想我必须使用while true
直到可以读取内容,因为如果我立即通过while read
curl
,管道是空的。
知道我想直接将curl输出发送到上面构造中的读取输入。
我真的不想使用任何临时文件(这很容易解决这个问题我同意:))
编辑:这是存储在日志中的stderr上的curl动态curl输出:
######################################################################## 100.0%
0.2%
0.5%
1.1%
# 1.6%
# 2.6%
## 3.3%
### 4.6%
#### 6.1%
#### 6.5%
#### 6.8%
##### 7.3%
##### 7.7%
##### 8.0%
##### 8.2%
###### 8.7%
答案 0 :(得分:3)
如果您想报告&#34;下载...&#34;当curl正在下载时,你可能想要做这样的事情(注意 - 有点高级bash hacking):
curl "$url" -o "$outfile" -vs > >( # redirect stdout to sub-shell, note the space
# parse curl's "verbose" output which tells us what is happening
# while we use -s to silence the standard progress bar which is useless for this
while read line; do # read verbose progress messages
if grep -q "Connected" <<<"$line"; then # wait for curl to connect
echo "Downloading..."
break
fi
done
cat > /dev/null # make sure to consume all stdin if we break early, to prevent "broken pipe"
) 2>&1 || echo "Error!"
我使用进程替换将输出定向到子shell的原因是不丢失curl退出代码,如果出现错误则该代码将为非零,允许我使用bash逻辑评估来报告错误(或我可以从$?
捕获它并检查它 - curl有非常详细的退出代码报告,所以我可以找出退出代码出了什么问题。详情请咨询man curl
。
还要注意2>&1
的位置,它将标准错误流重定向到标准输出流,以便进程替换可以获取通常发布到错误流的卷曲进度消息。这个重定向必须在stdout捕获之后,否则它只会创建一个stdout的副本,并且子shell将不会得到任何东西。关于流复制的Bash手册部分更好地解释了这一点。
上面的代码中有几个问题:
*)而不是
... -o "`echo $filename`" ...
你应该做的
... -o "$filename" ...
当你想要做的就是让bash扩展$filename
作为-o
参数的值时,没有理由进行额外的间接。
*)这没有道理:
read <&1
文件描述符1
是标准输出 - 你真的不想从中读取。如果您想从标准输入读取,则无需重定向 - read
默认情况下从标准输入读取。
*)这不是一个好习惯:
if [ "`echo $var | grep -o "value"`" == "value" ]; then
有很多原因 - 首先,grep -o
几乎没用,尤其是简单的文本搜索,因为它只会输出您想要查找的内容(取决于是否找到了值),这些内容完全映射到grep
退出代码为0或1.因此,只需执行if echo $var | grep -q "value"; then
即可。如果grep
成功,则此表达式将成功,否则将失败。 -q
用于使输出静音,因为您不需要它(只要它成功或不成功)。此外,如果您在变量中包含文本,则使用echo
将其移至grep
只会令人讨厌(它会打开子shell和分叉),而是说grep -q "value" <<<"$var"
。< / p>
最后,关于报告curl
是否正在下载,我个人认为curl
进度指标已经足够好了,但如果不是,那么只需用-s
将其静音。< / p>