Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'd like to implement a bash script that creates a mapping between the network cards (or interfaces) names in my computer and their IP address (in CIDR format, if possible).

The goal is having something like an associative array, or a file looking like:

lo: "127.0.0.1/8"
eth0: "192.168.1.123/24"
br-priv: ""      # <-- No IP assigned
wlan0: "10.42.0.10/24"

I have the ifconfig and the ip commands available, but the parsing of their outputs is a bit tricky, because the IP address and the interface's name don't appear in the same line so I would have to find the interface IP address and then rollback to find the network's name, or viceversa.

Is there any other way to find my interfaces IP addresses?

I have all the interfaces names (as directory names) under /sys/class/net/

root@borrajax:~# ls /sys/class/net/
br-priv/   eth0/    lo/    mon0/   wlan0/

But I haven't been able to find their IP in those directories. Doing that would be great, because I could just walk the directory, retrieve the directory's name and then read the IP from some other file.

This is intended to run in an embedded system running OpenWRT, but a solution for a Debian based system might be suitable. My bash's version is 4.2.28, just in case.

share|improve this question
2  
Just a note, a single interface can have any number of IP addresses –  Patrick Jul 7 at 13:57
    
@Patrick, you are very right, but in this particular case, this doesn't happen :-) but thanks for pointing in out –  BorrajaX Jul 7 at 15:15

1 Answer 1

up vote 5 down vote accepted

Use the "-o" option of ip:

ip  -o addr  | sed -e 's/^[0-9]: \([^ ]*\).*inet \([^ \t]*\).*/\1: "\2"/;t;s/^[0-9]*: \([^ :]*\).*/\1: ""/g' | sort -r | sort -u -t: -k1,1

Output should be then in your case:

br-priv: "" 
eth0: "192.168.1.123/24"
lo: "127.0.0.1/8"
wlan0: "10.42.0.10/24"

The command prints only one IPv4 per network device (it is possible to configure multiple IP addresses at the same interface).


Explanations:

The sed expression

s/^[0-9]: \([^ ]*\).*inet \([^ \t]*\).*/\1: "\2"/;

replaces 1: lo inet 127.0.0.1/8 brd 255 [...] with lo: "127.0.0.1/8"

t;

jump to end if this could be done (=an IPv4 address was found), otherwise:

s/^[0-9]*: \([^ :]*\).*/\1: ""/

replace lines without IPv4-addresses e.g. 1: lo inet6 ::1/128 [...] with lo: "".

All lines are automatically printed out (no -n flag).

The command sort -r sorts now the line reverse. The lines with IPv4-addresses (e.g. lo: "127.0.0.1/8") are then in all cases before the lines without (lo: "").

The command sort -u -t: -k1,1 applies unique sorting to the first field (the interface names, separator is set to :). In our example only the "lo: "127.0.0.1/8" line survive as it comes first (due to the previous sorting).

share|improve this answer
    
Wow, that is one ugly sed. –  Patrick Jul 7 at 14:35
    
@Patrick There are two regexp in the sed call: One for lines with IPv4 addresses, and one otherwise. The sort calls at the end filter duplicated lines and sort wrong lines out. –  jofel Jul 7 at 14:37
    
@jofel: If you have time, could you explain (very briefly) the idea between the two sed expressions? Please? –  BorrajaX Jul 7 at 15:19
    
@BorrajaX I added an explanation and simplified a bit the sed command. –  jofel Jul 7 at 16:57
    
@jofel: Thanks for taking the time to explain the sed... Even though I had already accepted the answer ;-) –  BorrajaX Jul 7 at 16:59

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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