Lately, I have been experimenting with the ps command, and sometimes long paths wrap to the next line (or two) and make it hard to read. I want to pipe the ps output into another program to limit the output to x number of characters.

Here is what I have so far, but it doesn't work quite right:

ps aux | cut -c1-$(stty size | cut -d' ' -f2)

$(stty size | cut -d' ' -f2) evaluates to 167, but doesn't seem to be valid input for cut.

Is there a way to get this type of syntax to work in bash?

  • This work for me. Can you provide some output? – cuonglm Apr 18 '14 at 4:29
  • where is the dynamic part? You want a different length for certain conditions? It seems like you want to limit all output to one maximum length – user61786 Apr 18 '14 at 4:29
  • @awk_FTW Depending on the situation, I have different window settings. At fullscreen, my width is 167. But at other sizes, I will need to be smaller. That's why I want to call ssty to get the size. – lentils Apr 18 '14 at 4:34
  • Try tput rmam; ps aux – Stéphane Chazelas Apr 18 '14 at 5:53
  • Some shells like zsh, ksh93 or bash store the terminal width in $COLUMNS – Stéphane Chazelas Apr 18 '14 at 5:56

The following works:

ps aux | cut -c1-$(stty size </dev/tty | cut -d' ' -f2)

This also works:

v=$(stty size | cut -d' ' -f2) ; ps aux | cut -c1-$v

The problem seems to be that stty needs to have the tty on its standard input in order to function. The above two approaches solve that.

There is still another option. While stty's stdin and stdout are both redirected in the above commands, its stderr is not: it still points to a terminal. Strangely enough, stty will also work if it is given stderr as its input:

ps aux | cut -c1-$(stty size <&2 | cut -d' ' -f2)
  • Indeed, it does! This was exactly what I was looking for. Just curious, why did you add the tee tt at the end? – lentils Apr 18 '14 at 4:39
  • @lentils Oops, the tee was added when I was debugging. It is gone now. – John1024 Apr 18 '14 at 4:41
  • What does <&2 refer to? I have never seen that notation before. – lentils Apr 18 '14 at 5:00
  • @lentils In the shell, files are numbered. Zero refers to standard input, one to standard output, and two to standard error. The expression <&2 means get your input from standard error. – John1024 Apr 18 '14 at 5:21
  • 1
    stty gets the settings of the terminal opened on its stdin (you do stty < /dev/other-tty to get the settings of another terminal for instance). So it's not strange that it won't work if its stdin is a pipe or that <&2 works. – Stéphane Chazelas Apr 18 '14 at 5:58

Some shells like zsh, bash or mksh automatically set the $COLUMNS variable to the width of the terminal, so you don't need to invoke stty here.

All the implementations of ps I tried that support that non-standard (BSD-type) syntax query the terminal width by themselves. I'm surprised yours doesn't. I expect it will look at the content of the COLUMNS environment variable though.

So you could do:

export COLUMNS; ps aux

If not,

ps aux | cut -c"1-$COLUMNS"

You can also tell your terminal not to wrap lines:

tput rmam
ps aux

You can also handle ps output a little better.

ps --width ${n:-$COLUMNS} ${opts} #set ps terminal width

ps -ww ${opts} #no word wrap

ps -o ${only_interesting_output} ${opts} #trim output

That will tell ps to parse its output to your specifications as necessary.

Of course, if you don't word wrap, though, then you've got the problem of missing info. Do you really need all of it for all processes? Open it in a pager if so:

ps ww ${opts} | $PAGER

If not, specify what you do want to see:

ps -o args= -p $pid

Alternatively you can explicitly inform ps of your terminal --width:

man ps


w Wide output. Use this option twice for unlimited width.

-w Wide output. Use this option twice for unlimited width.

--width n Set screen width.

The --width thing works exactly to your requested specs without having to involve any additional filters or ancillary processes (which will likely only clutter your -aux output even more). And with $COLUMNS as shown above and as Stephane points out it will even work dynamically.

It's probably worth noting, though, that I find people often try to add these kinds of unnecessary filters so they can accomodate a |pipe through another filter to parse output which is also pretty likely to be unnecessary. Of course, by people I mostly mean me.

The -output operand I mention above allows you to filter which columns ps displays, and when you add the =assigment you can even name the column as you please. I leave the assignment empty and hand it a target -process $pid so the only output from ps at all is the $pid command name and its args at invocation. And -o barely scratches the surface of how you can define what ps will or won't display. This is the direction I would recommend you take, especially via:

man ps


To see every process on the system using BSD syntax:

ps ax

ps axu

To print a process tree:

ps -ejH

ps axjf

To get info about threads:

ps -eLf

ps axms

To get security info:

ps -eo euser,ruser,suser,fuser,f,comm,label

ps axZ

ps -eM

To see every process running as root (real & effective ID) in user format:

ps -U root -u root u

To see every process with a user-defined format:

ps -eo pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,comm

ps axo stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm

ps -Ao pid,tt,user,fname,tmout,f,wchan

Print only the process IDs of syslogd:

ps -C syslogd -o pid=

Print only the name of PID 42:

ps -p 42 -o comm=

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.