Displaying only single most recent line of a comma

2019-03-03 03:05发布

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 to have something like this :

From:

removed /path/file1
removed /path/file2
removed /path/file3

To : Line 1 : removed /path/file1

Then : Line 1 : removed /path/file2

Then : Line 1 : removed /path/file3

EDIT : I may have been misunderstood, I want to have the whole process beeing printing in a single same line, changing as the command outputs an another line (like removed /path/file123)

EDIT2 : The output is sometimes too long to be display in on line (very long path). I would need something that considers that problem too :
/very/very/very/long/path/to/a/very/very/very/far/file/with-a-very-very-very-long-name1
/very/very/very/long/path/to/a/very/very/very/far/file/with-a-very-very-very-long-name2
/very/very/very/long/path/to/a/very/very/very/far/file/with-a-very-very-very-long-name3

2条回答
Fickle 薄情
2楼-- · 2019-03-03 03:39

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.

查看更多
闹够了就滚
3楼-- · 2019-03-03 03:39

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.

查看更多
登录 后发表回答