Displaying only single most recent line of a command's output

后端 未结 2 404
花落未央
花落未央 2021-01-24 19:18

How can I print a command output like one from rm -rv * in a single line ? I think it would need \\r but I can\'t figure out how.

I would need

相关标签:
2条回答
  • 2021-01-24 20:09

    Here's a helper function:

    shopt -s checkwinsize # ensure that COLUMNS is available w/ window size
    
    oneline() {
      local ws
      while IFS= read -r line; do
        if (( ${#line} >= COLUMNS )); then
          # Moving cursor back to the front of the line so user input doesn't force wrapping
          printf '\r%s\r' "${line:0:$COLUMNS}"
        else
          ws=$(( COLUMNS - ${#line} ))
          # by writing each line twice, we move the cursor back to position
          # thus: LF, content, whitespace, LF, content
          printf '\r%s%*s\r%s' "$line" "$ws" " " "$line"
        fi
      done
      echo
    }
    

    Used as follows:

    rm -rv -- * 2>&1 | oneline
    

    To test this a bit more safely, one might use:

    for f in 'first line' 'second line' '3rd line'; do echo "$f"; sleep 1; done | oneline
    

    ...you'll see that that test displays first line for a second, then second line for a second, then 3rd line for a second.

    0 讨论(0)
  • 2021-01-24 20:15

    If you want a "status line" result that is showing the last line output by the program where the line gets over-written by the next line when it comes out you can send the output for the command through a short shell while loop like this:

      YourCommand | while read line ; do echo -n "$line"$'  ...[lots of spaces]... \r' ; done
    

    The [Lots of spaces] is needed in case a shorter line comes after a longer line. The short line needs to overwrite the text from the longer line or you will see residual characters from the long line.

    The echo -n $' ... \r' sends a literal carriage return without a line-feed to the screen which moves the position back to the front of the line but doesn't move down a line.

    If you want the text from your command to just be output in 1 long line, then pipe the output of any command through this sed command and it should replace the carriage returns with spaces. This will put the output all on one line. You could change the space to another delimiter if desired.

     your command  | sed ':rep; {N;}; s/\n/ /; {t rep};'
    

    :rep; is a non-command that marks where to go to in the {t rep} command.

    {N;} will join the current line to the next line. It doesn't remove the carriage return but just puts the 2 lines in the buffer to be used for following commands.

    s/\n/ /; Says to replace the carriage return character with a space character. They space is between the second and third/ characters. You may need to replace \r\n depending on if the file has line feeds. UNIX files don't unless they came from a pc and haven't been converted.

    {t rep}; says that if the match was found in the s/// command then go to the :rep; marker.

    This will keep joining lines, removing the \n, then jumping to :rep; until there are no more likes to join.

    0 讨论(0)
提交回复
热议问题