Ava Barbilla
Ava Barbilla

Reputation: 1053

cURL surpress progress stats after cURL download has finished

I have this simple script:

printf "* Download Status: Pending..."

# Get HTML content from homepage
homepage=$(curl -s "https://example.com/")
wait

printf "\r* Download Status: Successful\n"

The \r simulates carriage return and prints Download Status: Successful after the download finishes, hereby removing Download Status: Pending.... This works flawlessly.

If I omit the -s flag, curl will show the statistics until the download is complete.

I tried using something like:

printf "< Download Status: Pending...\n\n"

# Get HTML content from homepage
homepage=$(curl "https://example.com/")
wait

printf "\r\r\r\r\r\r> Download Status: Successful\n"

The reason for me using that many \r is because I'm leaving some space at the beginning (\n) and the curl statistics themselves are 3 lines long. I thought this might remove them but it obviously doesn't, instead it outputs both of the printf with the curl stats in between them!


ALTERED ANSWER

According to @jmd_dk 's genius use of variables, this worked for my case:

# Set ANSI codes as variables
esc="\x1b"
esc_up="${esc}[1A"
esc_erase="${esc}[K"
newline="\n"

# Display status before download
printf "* Download Status: Pending...${newline}${newline}"

# Initiante cURL & wait for HTML content from the homepage
homepage=$(curl "https://example.com/")
wait

# Delete all lines up to download status
printf "${esc_up}${esc_erase}"
printf "${esc_up}${esc_erase}"
printf "${esc_up}${esc_erase}"
printf "${esc_up}${esc_erase}"
printf "${esc_up}${esc_erase}"

# Display status after completion
echo "* Download Status: Successful"

I delete all lines else some parts of the curl stats will be showed, making the output messy.

Upvotes: 1

Views: 795

Answers (2)

Socowi
Socowi

Reputation: 27225

Carriage Return

\r does not delete it line, it moves the cursor to the beginning of the current line.
Example: echo Test; printf '\r_' will print _est.

To delete the current line using \r, you would have to use

printf '\r                                                      '

Note the spaces that will (hopefully) overwrite everything in the current line.

Cursor Movement

\r always stays in the same line. Multiple subsequent \rs will have the same effect as just one. To delete other lines you have to use other escape sequences, such as

  • \033[<N>A move the cursor up <N> lines.
  • \033[K erase to end of line (just like \r with lots of spaces).

Putting Everything Together

curl shows its progress in three lines. On top of them, there is your Download Status: Pending..." message. To erase them all

  • \r\033[4A go to the left and four rows up
  • \033[K\n delete the 1st line and go to the 2nd
  • \033[K\n delete the 2nd line and go to the 3rd
  • \033[K\n delete the 3rd line and go to the 4th
  • \033[K delete the 4th line
  • \r\033[4A go to the left and four rows up again
  • Download Status: Successful print the new message

This leaves us with the command

echo "* Download Status: Pending..."
homepage=$(curl "https://example.com/")
wait
printf '\r\033[4A\033[K\n\033[K\n\033[K\n\033[K' # delete 4 lines
printf '\r\033[4A'                               # reposition cursor
echo '* Download Status: Successful'

You can write the last three lines as one printf, but that would be even harder to read.

Alternative

If you don't mind loosing all the output (even the output from commands executed before your script), you can clear the complete screen with just one escape sequence: \033c.

echo "* Download Status: Pending..."
homepage=$(curl "https://example.com/")
wait
printf '\033c' # clear screen
echo '* Download Status: Successful'

Upvotes: 3

jmd_dk
jmd_dk

Reputation: 13100

One solution would be to make use of more complex (ANSI) escape sequences. Example (save this to a script before running):

esc="\x1b"
esc_up="${esc}[1A"
esc_erase="${esc}[K"
echo Line 1
echo Line 2
echo Line 3
sleep 3
printf "${esc_up}${esc_up}"  # Move cursor two up
printf "${esc_erase}"  # Delete current line
echo New

This will print the three lines, then move up two lines and overwrite the text. To understand esc_erase, try leaving this line out.

The world of ANSI escape sequences is vast an daunting. The above example should suffice for your immediate needs. Much more information is of course available.

Upvotes: 2

Related Questions