0

This is a problem I often encounter, this time with the output of lsof, but I am searching for a general solution for such problems: selecting a column.

Here I try to get the TYPE column of the output of lsof

COMMAND     PID   TID                USER   FD      TYPE             DEVICE     SIZE/OFF       NODE NAME
lsof      16113                      root  cwd       DIR               0,58        40960    7602184 /home/rubo77
lsof      16113                      root  rtd       DIR              259,7         4096          2 /
lsof      16113                      root    4r     FIFO               0,12          0t0     294763 pipe
lsof      16113                      root    7w     FIFO               0,12          0t0     294764 pipe
lsof      16648                      root  rtd       DIR              259,7         4096          2 /
riot-web   4399  4424               ruben   25u     unix 0xffff9543f9ad7000          0t0      53133 type=STREAM
thunderbi  4650  5835               ruben  DEL       REG              259,7                 2752546 /usr/share/icons/hicolor/icon-theme.cache
...

I tried

lsof|perl -lane 'print $F[5]'

But this sometimes gets the 6th column, sometimes the 5th

I get it with

lsof|cut -c50-54|sort|uniq -c

375  CHR 
610  DIR 
211 FIFO 
...

But this seems a bit unclean because you have to fix the character position.

The main problem is, that in some lines the 5th column is empty

Is there a solution that really selects only the 6th column of an output?

The best solution would be a tool where you just say show the Xth line, where the tool would analyse the first line and automatically detects by analysing the following lines if each column is aligned right, centre or left and then just select the content of that column.

rubo77
  • 28,966

3 Answers3

1

You can use the -F option to get output more suitable for parsing e.g.

lsof -F t | awk '/^t/ {print substr($0,2)}'

See the OUTPUT FOR OTHER PROGRAMS section of man lsof


More generally, unless your fields are delimited unambiguously you may need to resort to searching for the character position in the header line e.g.

awk -v field="TYPE" 'NR==1 {c = index($0,field)} {print substr($0,c,length(field))}'
steeldriver
  • 81,074
  • fine, that works, but it is hard to understand, how. can you add an example how to get the FD column too? – rubo77 Dec 31 '18 at 14:56
  • @rubo77 you would need to use index and substr twice - once for each of the desired fields – steeldriver Dec 31 '18 at 15:01
  • Ah, I got it: lsof|awk -v field="FD" 'NR==1 {c = index($0,field)} {print substr($0,c-1,length(field)+4)}'|sort|uniq -c|sort -n – rubo77 Dec 31 '18 at 15:59
  • The best solution would be a tool where you just say show the Xth line, where the tool would analyse the first line and automatically detects by analysing the following lines if each column is aligned right, centre or left and then just select the content of that column. I am sure such a tool already exists – rubo77 Jan 01 '19 at 06:53
0

Using awk you can do this:

lsof | awk '{print $5}'

This will print out the number 5 column.

  • This does't work, I corrected my question, it is really the 6th column, but in some lines the 3rd column is empty – rubo77 Dec 31 '18 at 14:10
0

Select the column you want based on the number of columns in a row:

lsof | perl -ane 'printf "%s\n",(@F>9) ? $F[5] : $F[4]'

Perl numbers elements starting at zero. The -a switch auto-splits the input string (row) into Fields indexed from zero.

JRFerguson
  • 14,740