views:

590

answers:

6

Hello all,

I am attempting to write a bash script and I am having difficulty making the output look neat and organized. I could fall back on just using newlines, but I would much rather have output that was easy to read. For instance, when I run git clone ..., I want to first echo "Cloning repository" and then have the output of git indented. Example output:

Cloning repository...
    Initialized empty Git repository in /root/client_scripts/jojo/.git/
    remote: Counting objects: 130, done.
    remote: Compressing objects: 100% (121/121), done.
    remote: Total 130 (delta 13), reused 113 (delta 6)
    Receiving objects: 100% (130/130), 176.07 KiB, done.
    Resolving deltas: 100% (13/13), done.

Currently, it's all compressed with no indentation. Does anyone know how to do this? I attempted with sed and awk but it didn't seem to show any more output than just Initialized empty Git repository in /root/client_scripts/jojo/.git/. I would greatly appreciate any comments.

+4  A: 

Pipe through

sed "s/^/    /"

This will replace the (zero-width) anchor for line start by four spaces, effectively adding four spaces at the start of the line.

Joey
You could put a literal tab character in there too, if that's what you want.
Carl Norum
I already tried this, unfortunately, it outputs only the first line ("Initialized empty..."). My guess is that the rest of the information is output to STDERR but I can't seem to figure out how to redirect it.
Topher Fangio
Use I/O redirection to capture STDERR
David Harris
@Topher: a quick way to determine what's going to stdout is `command | less` : less will only catch stdout, and you won't see anything that went to stderr. Well, it might show up until you press j/k/up/down to "refresh" the page.
Mark Rushakoff
Topher Fangio
David Harris
This isn't going to work with git progress messages as most git progress messages are prefixed with `^M`, not a newline, and suffixed with `ESC [ K` to clear the rest of the line. Piping through sed is going to buffer the output, losing the interactivity of the updates.
Charles Bailey
So we have a conflict of interest here: visually updating updates and indentation. Depending on what the OP wants, it may be possible to either tell git to stop messing with the terminal and simply output text or lose indentation. Both suboptimal for certain use cases, I think.
Joey
+1  A: 

You can filter the output from the command you want to indent through sed.

/tmp/test>cat script
#!/bin/sh

echo "Running ls -l"
ls -l 2>&1 | sed 's/^/\t/'

/tmp/test>sh script
Running ls -l
        total 4
        -rw-rw-r-- 1 hlovdal hlovdal 55 2009-11-03 23:36 script
/tmp/test>

The sed command will replace the beginning of the line (before the first character) with a tabulator, i.e. insert a tabulator at the very beginning of the line.

Updated to also indent stderr.

hlovdal
Unfortunately, this doesn't capture the necessary output from git. Still only outputs the first line...
Topher Fangio
A: 

Add the required spaces at the start of the lines that need them.

echo "    erty"
David Harris
A: 

A different solution that doesn't require sed:

command | (while read; do echo "    $REPLY"; done)
Juliano
You're missing the read variable; fix: `comand | while read REPLY; do echo " $REPLY"; done'
Ryan Bright
@Ryan Bright: No, read the Bash manual, the REPLY variable is implied. Or just type this in a shell and test it for yourself.
Juliano
A: 

Since the awk solution wasn't posted yet:

$ echo -en "hello\nworld\n"
hello
world
$ echo -en "hello\nworld\n" | awk '{print "    "$0}'
    hello
    world
Mark Rushakoff
+2  A: 

The problem with piping the output of git through any command is that git will detect that the output is not a terminal so it won't output messages which are progress messages because (typically) it is not useful to pipe a whole lot of terminal characters and progress updates to something that isn't a terminal.

To get the progress messages anyway you need to provide the --verbose option to git clone. The progress messages appear on stderr so you are likely to need a pipe something like 2>&1 | ... .

Be aware the the progress messages won't appear line by line, but you'll get a lot of terminal escape codes which are designed to clear the same line. Trying to indent this output by piping through a line based tool like sed is likely to prove difficult, if not impossible. For a program that can handles input unbuffered, it should be fairly possible to look for a ^M in the output and add some spaces (or a tab) immediately aftwards, flushing as often as each batch of data is received.

Charles Bailey
Thanks for the information, however, neither my version of git (1.5.6.5) nor the latest have --version as an option to either git or git-clone. I guess I am simply out of luck if I want to do this. Thanks for the info on git detecting that it isn't on a terminal.
Topher Fangio
Err...I just reread my previous comment, I really did mean `--verbose` not `--version`.
Topher Fangio