如果命令更新行而不是添加新行,如何在命令的输出前面添加?

如果命令更新行而不是添加新行,如何在命令的输出前面添加?

我想在输出(进度)前添加rclone自定义文本。经过一番谷歌搜索后,我想出了这个解决方案:

rclone sync "$SOURCE" "$DESTINATION" | while read line; do echo "   $line"; done

但实际上 rclone (使用 --progress)在开始时抓取一些行,然后在执行期间更新它们。但是使用while我最终会不断添加新行而不是更新旧行。有人知道如何解决吗?

默认情况下rclone --progress output,每秒更新一次:

Transferred:             0 / 0 Bytes, -, 0 Bytes/s, ETA -
Checks:                97 / 97, 100%
Elapsed time:         0.0s

期望的输出:

[My text] Transferred:             0 / 0 Bytes, -, 0 Bytes/s, ETA -
[My text] Checks:                97 / 97, 100%
[My text] Elapsed time:         0.0s

的实际结果while,它不会更新,而是添加:

[My text] Transferred:             0 / 0 Bytes, -, 0 Bytes/s, ETA -
[My text] Checks:                97 / 97, 100%
[My text] Elapsed time:         0.0s
[My text] Transferred:             0 / 0 Bytes, -, 0 Bytes/s, ETA -
[My text] Checks:                97 / 97, 100%
[My text] Elapsed time:         0.0s
[My text] Transferred:             0 / 0 Bytes, -, 0 Bytes/s, ETA -
[My text] Checks:                97 / 97, 100%
[My text] Elapsed time:         0.0s
[My text] Transferred:             0 / 0 Bytes, -, 0 Bytes/s, ETA -
[My text] Checks:                97 / 97, 100%
[My text] Elapsed time:         0.0s

答案1

我不确定我是否理解你的问题。如果你想要做的是不断更新同一行,你可以使用类似:

rclone sync "$SOURCE" "$DESTINATION" | while read line; do echo -en "   \r$line"; done

-n 将停止回显以打印尾随换行符

-e 将指示 echo 评估反斜杠序列

答案2

控制这种类型的更新很困难,主要是因为并非所有程序都发送完整的更新数据并且始终处于相同的位置。在这种特殊情况下,rclone似乎每秒发送三个完整的数据行,因此我们必须修改它们并在同一位置重绘并擦除旧的数据行,因为如果新的比旧的短,它们会在屏幕上混合。对我来说,最简单的方法是使用clear命令并在每次重绘时仅显示左上角的数据行:

rclone sync "$SOURCE" "$DESTINATION" | while read line; do if echo "$line" | grep -q  "Transferred"; then clear; fi ; echo "   $line"; done

如果我们想要更多的控制,我们可以使用 ANSI 转义光标位置代码将每个特定的输出行精确地放置在某个预定义的屏幕位置,用于grep确定当前正在打印哪一行。或者,我们可以read A B C... <<<$line从每一行中提取单个数据字段,并根据需要完全重新组织输出。当然,存在更有效的方法来做到这一点,也许使用awk等。警告:即使rclone取消缓冲其输出,也可能有必要对while命令上的 stdin/stdout 执行此操作,以保证及时重绘 - 我没有做任何操作测试。

我建议将命令分组在一个脚本中,例如rclone.format.sh,以简化调用和调试:rclone sync "src" "dst" | ./rclone.format

#!/bin/bash
# formatting rclone progress output
# use: rclone [options] | rclone.format.sh
#--------------------
TXTPFIX="my customized progress text"

while read LINE ; do
  if echo "$LINE" | grep -iq transferred ; then
    #-- erase screen on first line detected
    clear
  fi
  #-- send modified line
  echo "$TXTPFIX $LINE"
done
#-- end --#

不要忘记chmod u+x rclone.format.sh允许简单的脚本执行。

相关内容