Say I'm writing a .bashrc file to give me some useful information in my login terminals and I'm telling it to run the cal command (a nice one). How would I go about shifting the calendar produced to the right to match the formatting of the rest of my .bashrc "welcome message"?
- 807,993
- 194
- 1,674
- 2,175
- 303
- 1
- 4
- 11
5 Answers
cal | sed 's/^/ /'
Explanation
cal |: pipe the output of cal to…sed 's/^/ /'sed, which will look for the start of lines^, replacing with spaces. You can change the number of spaces here to match the required formatting.
Edit
To preserve the highlighting of the current day from cal, you need to tell it to output "color" (highlighting) to the pipe. From man cal
--color [when]
Colorize output. The when can be never, auto, or always. Never will turn off coloriz‐
ing in all situations. Auto is default, and it will make colorizing to be in use if
output is done to terminal. Always will allow colors to be outputed when cal outputs
to pipe, or is called from a script.
N.B. there seems to be a typo in the manual; I needed a = for it to work. Hence, the final command is
cal --color=always | sed 's/^/ /'
- 19,561
- 18
- 86
- 152
-
I just realized that for a command like `cal` the highlighted day is lost. Is there a way to keep it? – theStandard Aug 03 '14 at 09:28
-
@theStandard Good point! I've edited in the information. – Sparhawk Aug 03 '14 at 10:37
-
`--color=always` doesn't work for me – theStandard Aug 03 '14 at 22:51
-
@theStandard I guess try `--color always`? What does `man cal` say for you? – Sparhawk Aug 04 '14 at 00:08
-
1@theStandard This is for `cal from util-linux 2.24.2` (obtainable with `$ cal --version`). – Sparhawk Aug 04 '14 at 10:44
-
This works great but when the command I'm running is `scp` it fails to output anything. My guess is it's down to the way `scp` outputs things. Any ideas? – Adrian Lynch Nov 15 '19 at 11:07
-
@AdrianLynch Are you talking about secure copying (`scp`) a file over the network? I wouldn't expect `~/.bashrc` to execute during `scp`. – Sparhawk Nov 15 '19 at 11:17
-
@Sparhawk - I'm running something like `scp server:/path/*.log ./ | sed 's/^/ /'` but it fails to pass the output through sed. – Adrian Lynch Nov 15 '19 at 12:59
-
This question is about piping and reformatting the output of `cal`. Your first command `scp server:/path/*.log ./` wouldn't show any (unformatted) `cal` output, right? So there's nothing to pipe into the `sed` command. – Sparhawk Nov 15 '19 at 22:28
cal | nl -bn
...will work because nl always indents input lines it doesn't number to equal the indent it would add to those it does. By default nl does not number -header or -footer sections of input, and only numbers -body lines. If you also tell it not to number -body lines it will number nothing at all and only insert indentation to every input line.
Use the -width and -separator switches to adjust the size of the indent.
cal; cal | nl -bn
December 2015
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
December 2015
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
There is also:
cal | pr -to[num]
...where [num] is the number of spaces you want inserted at the head of each line. pr usually prints 66 lines per page, but the -t tells it to omit its header/footer inserts and just print input to output. The -offset margin switch is then used to insert as many spaces as are requested in [num] at the head of each output line:
cal; cal | pr -to10
December 2015
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
December 2015
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
- 57,448
- 9
- 113
- 229
With paste:
cal | paste /dev/null -
paste pastes the lines of files together with TAB characters in between. Here we paste the empty file (/dev/null) with paste's stdin (-) which is the output of cal fed via a pipe.
- 522,931
- 91
- 1,010
- 1,501
-
-
1
-
Now I understand the dash `-` is a `paste` parameter to indicate to take the stdin. I though it was the delimiter hehe. Maybe another example more didactic would be `cal | paste /dev/null -d"\t" -` where you can see the delimiter more clearly. Thanks. – august0490 Mar 27 '21 at 06:28
-
@august0490, in POSIX compliant `paste` implementations, that would paste the `/dev/null`, `-d\t` files and stdin. Options need to go before non-option arguments. Bear in mind that `-d string` doesn't insert `string` in between columns but `s` between the first and second, `t` between the 2nd and 3rd, etc. – Stéphane Chazelas Mar 27 '21 at 06:42
You can use sed:
cal | sed -e 's/^/ /'
The above will indent the calendar by four spaces by inserting them at the start (^) of every line. You can change the indentation as you wish, or add other pieces of output.
If you want it perfectly right-aligned in any terminal you can use printf and stty with a more ugly loop:
read height width < <(stty size)
cal | while read line ; do printf "%${width}s" "$line" ; done
(stty size is non-standard but widely supported)
- 74,824
- 17
- 212
- 233
-
-
Is there a way to put the output of two commands next to each other? – theStandard Aug 03 '14 at 08:00
-
You can use `curses` (or terminal escapes) to set things up that way, but it's a pretty fraught process. Other than that, one neat trick: if the command output is substantially different, you can trick `diff` into making a side-by-side diff of both: `diff -y -W 80 <(some command) <(cal)`. – Michael Homer Aug 03 '14 at 08:18
-
1
Here is example using ex:
ex +"%norm 20I " +%p -scq! <(cal)
Change 20 into number of required spaces. Using "%norm 20I " is more efficient than repeating many spaces with substitution - "%s/^/ /".
- 20,250
- 14
- 140
- 164
-
`ex` can read stdin. and it will quit at eof automatically if it does - why `<(`thing`)`? – mikeserv Dec 31 '15 at 07:52
-
@mikeserv Seems it doesn't quit on eof: `cal | ex +"%norm 20I " +%p /dev/stdin` (you've to manually type `q!`). `<()` instead of pipe, otherwise you need to write `/dev/stdin`, so it's longer and doesn't look clean: `cal | ex +"%norm 20I " +%p -scq! /dev/stdin`. – kenorb Dec 31 '15 at 11:27
-
-
@mikeserv `-` it seems it doesn't work: `cal | ex +"%norm 20I " +%p -scq! -` – kenorb Dec 31 '15 at 11:29