14

In Ubuntu 16.04 I made a script to dinamically configure IP address of the wired ethernet interface based on certain parameters. Now the problem is that in my script I assume that the name is eth0, but this is not always true.. assuming that I have only one wired network interface (not necessary plugged) but I can have also a wireless interface, how can I retrieve its name (just the wired one)?

with ifconfig command I get:

enp7s0    Link encap:Ethernet  HWaddr fc:3f:db:a2:6d:46  
          inet addr:192.168.0.101  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::149f:3103:af2f:1ec5/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6784 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7493 errors:1 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4565079 (4.5 MB)  TX bytes:827825 (827.8 KB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:8037 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8037 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:2261250 (2.2 MB)  TX bytes:2261250 (2.2 MB)

wlp19s0   Link encap:Ethernet  HWaddr c8:ff:28:93:26:32  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:180463 errors:0 dropped:0 overruns:0 frame:0
          TX packets:121275 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:229823414 (229.8 MB)  TX bytes:15675806 (15.6 MB)

What I want is:

enp7s0
6
  • 1
    I think you want something like ip link | awk -F: '$0 !~ "lo|vir|^[^0-9]"{print $2a;getline}' Apr 6, 2017 at 14:12
  • this will show also the wireless adapter
    – rok
    Apr 7, 2017 at 8:35
  • #rok, it does but aren't you mentioning it in your question as well? but I can have also a wireless interface, how can I retrieve its name Apr 7, 2017 at 10:40
  • edited with details, please see
    – rok
    Apr 7, 2017 at 10:55
  • 1
    Ok then this will fix it: ip link | awk -F: '$0 !~ "lo|vir|wl|^[^0-9]"{print $2a;getline}' Apr 7, 2017 at 12:37

7 Answers 7

12

If you want to exclude interfaces like vir , loopback and wl(wireless) then the following should do the trick.

ip link | awk -F: '$0 !~ "lo|vir|wl|^[^0-9]"{print $2;getline}'

Here we use colon as delimiter -F: then check if the row $0 does not match a certain string using regular expression.

Update: Using the -brief flag as suggested in the comment, the command changes to:

ip -br l | awk '$1 !~ "lo|vir|wl" { print $1}'
6
  • Don't forget tun for future readers.
    – Drakes
    Oct 23, 2019 at 4:26
  • 1
    Instead of complicated awk, use -brief flag of ip command: ip -br l | cut -d\ -f1 ... Then you could | grep -v '^w\|^lo$' ... Jul 23, 2022 at 12:11
  • Thanks for the feedback. But now you are introducing 2 processes cut and grep. The filtering still needs to happen. Jul 23, 2022 at 14:22
  • 1
    Don't forget ppp, vcan, can, docker, br and countless other examples that are not Ethernet. In other words, this method is crapshoot.
    – rustyx
    Oct 27, 2023 at 13:33
  • To select ethernet only is it possible to use the fact ifconfig contains mtu 1500 for ethernet? Jan 8 at 9:52
17

Because all interfaces would displayed under /sys/class/, such as /sys/class/net/ listing all network interfaces,

it is possible to directly use this directly search and return the exact interface name through a simple keyword like:

ls /sys/class/net | grep enp

1
  • 5
    If you want to include interfaces like "eth0" as well, change the grep from enp to ^e and it will match both eth* and enp*
    – Enrico
    May 4, 2019 at 15:34
7

Here is best solution

ip route get 8.8.8.8 | awk -- '{printf $5}'

or

echo $(ip route get 8.8.8.8 | awk -- '{printf $5}')

in bash script you can declare main_interface and use anywhere as $main_interface

main_interface=$(ip route get 8.8.8.8 | awk -- '{printf $5}')

3
  • As it stands, means a trip out to a google site but I like it as a way of finding which interface is actually being used to reach the web or a particular site. Jul 26, 2021 at 12:48
  • 1
    Sorry, I have to muddle my comment just made above. I don't actually know that a trip was made to the site. I'm seeing the same valid results even when I enter an address I know not to exist. So seems like a good way to see which interface the routing table is setup to use. Jul 26, 2021 at 13:24
  • 1
    This is a great simple way to check which interface is connected to your default gateway. Not sure why this isn't the top answer.
    – erwin
    Sep 13, 2021 at 7:54
4

I'd use ifconfig(bit old and deprecated) tool or ip command. Using ip route you are having a list of available routes. Then get only line containing default with grep and strip the unwanted characters off the string using sed

full command goes like:

ip route | grep default | sed -e "s/^.*dev.//" -e "s/.proto.*//"

4
  • It's only working if the ethernet port is connected, otherwise could also show the wireless adapter name if connected to a wifi network...
    – rok
    Apr 6, 2017 at 11:00
  • @rok don't you need the default interface always regardless of Ethernet or wireless?
    – inckka
    Apr 6, 2017 at 11:05
  • No.. I just need the Ethernet name
    – rok
    Apr 6, 2017 at 11:08
  • This would have been my answer. @rok your question sounds like you want the interface whether it is wired or wireless. Please edit your question to clarify.
    – chicks
    Apr 6, 2017 at 13:03
3

The trick is to get the list of interfaces from /sys/class/net and then look where they go to.

find /sys/class/net ! -type d | xargs --max-args=1 realpath | awk -F\/ '/pci/{print $NF}'

To filter on Ethernet only, you would have to grep lspci first:

lspci  | awk '/Ethernet/{print $1}'

The complete command becomes:

pci=`lspci  | \
 awk '/Ethernet/{print $1}'`; find /sys/class/net ! -type d  | \
 xargs --max-args=1 realpath  | \
 awk -v pciid=$pci -F\/ '{if($0 ~ pciid){print $NF}}'
2
  • no.. I also have a wireless interface
    – rok
    Apr 6, 2017 at 10:55
  • @rok Try the last command. Wireless interface won't show up as "Ethernet". That's the whole point of this solution. However, this solution won't work with USB Ethernet dongles.
    – rustyx
    Oct 27, 2023 at 14:04
1

Inspired by the answer from @千木郷, but not wanting to invoke any external processes, I'd use this:

$(basename /sys/class/net/en*)

That will return an error if there are multiple devices starting with en, but if you want them all you can add a -a to the basename command.

For wireless devices, use the prefix wl instead of en. The naming scheme rationale and the reference code for `builtin_net_id() provide more help.

0

Most ethernet interfaces start with e (eth or en) so you can just filter on that....

IFACE_NAME=$(ip --brief link | awk '{print $1}' | grep -E '^e.*' | tr -d '\n')
echo $IFACE_NAME
IFACE_ADDR=$(ip -4 --brief addr show dev $IFACE_NAME | awk '{print $3}' | cut -d'/' -f1 | tr -d '\n')
echo $IFACE_ADDR

If you want to be more robust you can do a wc -l to make sure you have 1 and only 1 matching interface name.

To be more deterministic you can parse files in /etc/sysconfig/network (redhat/centos) or /etc/network/interfaces or /etc/netplan/ etc to find interface names by type.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .