Linux command question

I have a friend who is taking a course and has a question that has him and apparently google stumped.. I copied his email to me.. I have no clue lol

The question
Give a command line starting with ps aux that will print only entries with square brackets around the command field of processes currently running.
Hint: You will need to use a pipe here and keep in mind that the COMMAND field comes last in the output

In a nutshell
I need to grep for specific words within ps aux only from the COMMAND column. I don't want to use awk.

It's all Greek to me.

I don't know if there's any way around using awk. Maybe he could use cut?

Crude and low-tech, but effective if the line format doesn't change considerably.

awk really is the best tool for the job here:

ps aux | awk '/ \[.+\]$/ {print}'

That said, you could implement the same functionality in some other scripting language (perl, for example), if absolutely necessary.

Actually, I take it back. egrep works fine in this case as well, if it's available on your system:

ps aux | egrep -e ' \[.+\]$'

egrep is not necessary, regular GNU grep will suffice. The trick is standardizing the delimiter for the ps aux output:

ps aux | tr -s ' ' | grep '^.* .* .* .* .* .* .* .* .* .* \[.*\]'

Since ps aux output is variable amount of spaces, transform all of it to just a single space to make it a reliable delimiter. Column of interest is after the 10th space character. Only match the brackets then. Also, not sure if all commands that have a bracket will end in close bracket so I left the line terminator out.

Sidenote: .+ should work but doesn't on my terminal.

Thanks for the suggestions.. I passed them along and hopefully that will satisfy his instructor.

Odd... he doesn't -want- to use awk or isn't allowed to?

If it's want, that kind of like saying he needs to change a twelve foot 2x4 into 2 six foot 2x4s, but doesn't want to use a saw.

Just thought it funny.

Not allowed to use awk was what I was told..the email was phrased oddly in comparison to the phone call.

The only thing about the examples as given is that they seem to also catch sshd priv sep shell processes (at least with my versions of grep / ps / etc):

root 7199 0.0 0.1 70840 4052 ? Ss 07:15 0:00 sshd: fred [priv]
root 27557 0.0 0.1 70840 4048 ? Ss May30 0:00 sshd: gary [priv]
root 36208 0.0 0.1 70840 4048 ? Ss May27 0:00 sshd: bob [priv]

Using cut to explicitly grab fields 1-11 after smushing the output together with tr will end up leaving those later fields off:

ps aux | tr -s ' ' | cut -f1-11 -d" " | grep '\[.*\]'

But I'm not sure which of those outputs would be preferred.

Edit: Misread the original question and thought they wanted just the command, not the full line. This should give the full line:

ps aux | grep '^.\{65\}\[.*\]$'

Assuming the command field is starting at the 66th character on each line.

Edit edit: And like Tyrian says, I'm assuming they just want kernel threads listed, and not processes with priv sep, which the earlier answers will catch.

If it's the last field then pipe through rev and then use cut to grab the first field with the same delimiter and pipe through rev again. That way you don't need to assume a character position for the command field.

Bash is brilliant at this sort of stuff.

Nice trick... but as the delimiters would be reversed, but not inverted, your search would have to be adjusted slightly... i.e. the line would look like:


The format of the time column isn't going to appear anywhere else in the output, so you can grep for that:

ps aux|grep -E ' [0-9]+:[0-9]{2}(\.[0-9]+)? \['

(edit) Also, using rev and checking the first field won't work, because the command can have spaces in it.

If you rev the line, the closing square bracket is the first character:

ps -aux | rev | grep "\].*" | rev

That way you don't have to make assumptions about the character position of any of the fields, which varies between my busybox embedded rootfs and Fedora 15 ps commands.

To also reject the privs you'd have to finally pipe it through an inverse grep:

ps -aux | rev | grep "\].*" | rev | grep -vF "\[priv\]"

I'm picking up good stuff in this thread!