Unrar和进度条Bash

Unrar和进度条Bash,bash,Bash,我试图用unrr命令提取目标目录中的RAR文件,但我不想显示unrr执行时显示的普通文件列表。我想做的是,使用对话框--gauge显示一个进度条,以百分比的形式显示流程,但到目前为止,我只得到了错误 语法错误:意外的文件结尾 以下是我使用的代码: #!/bin/bash dest="testing" file"example.rar" cmd="$(unrar x "$file" "$dest")" &>/dev/null fc="$(unrar l "$file" | wc -

我试图用unrr命令提取目标目录中的RAR文件,但我不想显示unrr执行时显示的普通文件列表。我想做的是,使用
对话框--gauge
显示一个进度条,以百分比的形式显示流程,但到目前为止,我只得到了错误

语法错误:意外的文件结尾

以下是我使用的代码:

#!/bin/bash
dest="testing"
file"example.rar"
cmd="$(unrar x "$file" "$dest")" &>/dev/null

fc="$(unrar l "$file" | wc -l)" # get file count inside RAR file
fc="$((fc-10))" # file count has 10 extra lines, remove them
i=0  # index counter
(
  for f in "$cmd"; do
    pct="$(( 100*(++i)/fc ))"  # calculate percentage
    cat <<EOF
    XXX
    $pct
    Extracting file "$f"...
    XXX
    EOF
  done
) | dialog --title "Extracting Files" --gauge "Please wait" 7 70 0 
#/bin/bash
dest=“测试”
文件“example.rar”
cmd=“$(unrar x“$file”“$dest”)”和>/dev/null
fc=“$(unrar l“$file”| wc-l)”#获取RAR文件中的文件计数
fc=“$((fc-10))”#文件计数有10个额外的行,请删除它们
i=0#索引计数器
(
对于“$cmd”中的f,请执行以下操作
pct=“$((100*(++i)/fc))”计算百分比
cat/dev/null
但我无法使对话框正确显示


我从网上找到的各种示例中得到了这段代码,但到目前为止我还无法实现。有人能给我指出正确的方向吗?

好吧,既然没有人回答我的问题,我就自己来回答。我终于成功地使程序工作了,它提取文件,打印被提取文件的路径名,并显示在提取每个文件时正确填充量规。代码如下:

#!/bin/bash
dest="testing" # destination directory
file"example.rar"

(
fc="$(unrar l "$file" | wc -l)" # get file count inside RAR file
fc="$((fc-10))" # file count has 10 extra lines, remove them
i=0  # index counter
unrar x "$file" "$dest" | while IFS="" read -r in ; do
  # extract the pathname of file being extracted
  f=$(echo $in | cut -d ' ' -f 2)

  echo "XXX"
  echo "$f..." # Display file name in the dialog box
  echo "XXX"
  echo "$pct %" # Show percent
  pct="$(( 100*(++i)/fc ))" # Calculate current percent
done
) | dialog --title "Extracting Files" --gauge "Please wait" 8 75 0
下一部分应该捕获执行.RAR文件提取的结果,但是我不确定现在我只是捕获对话框的执行结果还是unrr命令的执行结果。我想做的是在unrr命令失败的情况下控制脚本的流程,我不完全确定应该怎么做继续,但是现在,在我显示对话框的那一行之后,我放置了以下if-then:

if [ "$?" ]; then
  clear
  echo "Command successful"
fi
这是正确的还是应该将if-then块移动到代码中的其他地方

同时,Imma以某种方式使该脚本像一种预绑定的UNRR命令一样工作,您可以在其中指定要提取的文件名和可选的目标目录,这样我就无需指定目标目录

编辑:

这是我用来解决我自己问题的当前代码。到目前为止,代码似乎处理错误很好。我只使用“文件已存在”进行了测试一种错误,用于停止脚本的执行以等待用户的输入,以及在将压缩文件划分为多个部分但其中一个部分丢失的情况下的CRC错误

#!/bin/bash
dest="testing" # destination directory
file="example.rar"

(
  fc="$(unrar l "$file" | wc -l)" # get file count inside RAR file
  fc="$((fc-10))" # file count has 10 extra lines, remove them
  i=0  # index counter

  # I have to redirect the output from 0 to 1 because when there's a
  # "file already exists" kind of error, unrar halts the execution of the
  # script to wait for user input, so I have to process that message inside
  # of the loop
  unrar x "$file" "$dest" 0>&1 2>&1 | while IFS="" read -r in ; do

    # we got a "file already exists" message?
    if [[ "$f" == *"already"* ]]; then
      echo "Error"  # display an error message
      break         # exit the while loop
    fi

    # extract the pathname of file being extracted
    f=$(echo $in | cut -d ' ' -f 2)

    echo "XXX"
    echo "$f..." # Display file name in the dialog box
    echo "XXX"
    echo "$pct %" # Show percent
    pct="$(( 100*(++i)/fc ))" # Calculate current percent
  done

  exit ${PIPESTATUS[0]} # exit with status message we got from unrar

) | dialog --title "Extracting Files" --gauge "Please wait" 8 75 0

# if PIPESTATUS[0] is not equal to zero, it means there was an error
if [[ "${PIPESTATUS[0]}" -ne 0 ]]; then
  echo "There was an error." # display a message
  exit 1  # exit with status 1
fi

# if command was successful, display a message  
if (( "$?" == 0 )); then
  echo "Command executed correctly $?"
fi

到目前为止,我没有对错误做任何处理,我只是对检测错误并将消息返回给调用此错误的脚本感兴趣。它似乎工作得很好,但我知道必须有更好的方法来完成此操作。你有什么想法?

如果[“$?”]
总是正确的。它完全等同于
[-n”$?]
,它询问
$?
是否扩展为空字符串。无论是0、1还是其他任何内容,它都始终是非空的。
如果[“$?”-eq 0]
可能是您的目标,或者bash-y等效的
如果(($?==0))
,尽管使用
$?
有点代码味道;最好直接将正在测试的命令放在
if
语句中。@CharlesDuffy我正在尝试测试unar执行的结果以捕获错误(您可能已经知道),但因为命令是在子shell中执行的(据我所知)然后子shell的结果被重定向到对话框(我认为这就是这里发生的事情),捕获子shell中的错误不会影响对话框的执行?我的目的是在出现错误时立即停止命令的执行。捕获此代码中的错误的最佳解决方案是什么?放置
exit${PIPESTATUS[0]}
直接在子shell内部的
完成之后
,然后您可以在子shell外部引用
${PIPESTATUS[0]}
以引用该管道的第一个元素(即子shell本身)。或者您可以
设置-o pipefail
。也就是说,我根本不会这样设置管道。最好使用进程替换。