Create an array with all network interfaces in bash

8,008

Solution 1

Here is a solution, assign the list and then add item to it:

#!/bin/bash

array_test=()
for iface in $(ifconfig | cut -d ' ' -f1| tr ':' '\n' | awk NF)
do
        printf "$iface\n"
        array_test+=("$iface")
done
echo ${array_test[@]}

If you want the output displayed one item per line:

for i in "${array_test[@]}"; do echo "$i"; done

To remove localhost from output:

if [ "$iface" != "lo" ] 
then
    array_test+=("$iface")
fi

Solution 2

My try:

readarray -t interfaces < <(ip l | awk -F ":" '/^[0-9]+:/{dev=$2 ; if ( dev !~ /^ lo$/) {print $2}}')
for i in "${interfaces[@]// /}" ; do echo "$i" ; done

Solution 3

ifconfig only outputs the interfaces that are up.

On Linux, you can get a list of interfaces in the /sys/class/net directory. So, with zsh, you can do:

interfaces=(/sys/class/net/*(DN:t))

To exclude lo:

set -o extendedglob
interfaces=(/sys/class/net/^lo(DN:t))

For only the up ones, you could do:

interfaces=(/sys/class/net/*(DNe{'[[ $(<$REPLY/operstate) = up ]]'}:t)

or, assuming the default value of $IFS.

interfaces=($(ip -br link | LC_ALL=C awk '$2 == "UP" {print $1}'))

On my system at least the status for lo is UNKNOWN so would be excluded.

That would also work with bash provided interface names don't contain wildcard characters. In recent versions of Linux, IIRC, interface names are guaranteed not to contain space tab and newline characters (the default $IFS), so those would not cause problem. Other Unicode blanks are allowed though, hence the LC_ALL=C which should guarantee that awk won't split on those.

Solution 4

bash will construct an array from any white-space delimited (spaces, tabs, newlines) list you give it. e.g. array=(a b c). We can use command substitution ($()) to generate such a white-space delimited list. For example:

$ ifaces=( $(ip addr list | awk -F': ' '/^[0-9]/ {print $2}') )

and now print out the array we just created:

$ declare -p ifaces
declare -a ifaces=([0]="lo" [1]="eth0" [2]="eth1" [3]="br1" [4]="br0" [5]="ppp0")

To exclude lo:

$ ifaces=( $(ip addr list | awk -F': ' '/^[0-9]/ && $2 != "lo" {print $2}') )
$ declare -p ifaces
declare -a ifaces=([0]="eth0" [1]="eth1" [2]="br1" [3]="br0" [4]="ppp0")

If you really want to use ifconfig rather than ip, try this:

ifaces=( $(ifconfig | awk -F':'  '/^[^ ]*: / && $1 != "lo" {print $1}') )

Solution 5

If you have '-j' support for ip (json output) then use the excellent jq utility;

# ip -j addr show | jq -r .[].ifname
lo
eth0
eth1
tunl0
gre0
gretap0
erspan0
ip_vti0
ip6_vti0
sit0
ip6tnl0
ip6gre0
dummy0
kube-ipvs0
cbr0
vethfbcab624

(example from a kubernetes node)

Share:
8,008

Related videos on Youtube

Georgi Stoyanov
Author by

Georgi Stoyanov

Updated on September 18, 2022

Comments

  • Georgi Stoyanov
    Georgi Stoyanov over 1 year

    I want to create an array in Bash which to contain all active network interfaces.

    I have managed to create a for loop printing them but when I try to create the array, it just contains the last lo interface but not the other. This is my code:

    #!/bin/bash
    
    for iface in $(ifconfig | cut -d ' ' -f1| tr ':' '\n' | awk NF)
    do
               printf "$iface%s\n"
               declare -a array_test=["$iface"]
    done
    for i in "${array_test[@]}"; do echo "$i"; done
    

    And this is my output:

    eno1
    eno2
    eno3
    lo
    [lo]
    

    Also, how can I exclude the lo localhost interface from the array?

    • Alessio
      Alessio over 6 years
      @peterh bash can be used for quite complex scripts (as can, e.g., ksh or zsh)....but the more complex it is, the harder it is to read, understand, and modify - and the slower it becomes (e.g. a loop around forking several programs is abysmally slow). At that point, the time/effort cost of writing and maintaining a shell script greatly exceeds the cost of learning the basics of awk (or perl, or python) and rewriting it in about 1/10th the lines of codes. If you already know one of those languages, then that point is reached much earlier.
    • Georgi Stoyanov
      Georgi Stoyanov over 6 years
      I am writing a script to emulate network impairments using iproute and tc command. I was using this array approach to check if the user defined variable is valid. I believe writing this script in python would be a bit painful and I am also using the opportunity to learn a bit of bash.
  • Georgi Stoyanov
    Georgi Stoyanov over 6 years
    how can I exclude the lo localhost interface from the array?
  • Kevin Lemaire
    Kevin Lemaire over 6 years
    added in answer and question
  • Georgi Stoyanov
    Georgi Stoyanov over 6 years
    Actually you can do the same just by removing the last item in the array, I have found the answer in the meantime: unset "net_array[${#net_array[@]}-1]"
  • Kevin Lemaire
    Kevin Lemaire over 6 years
    I won't do that because I'm not sure localhost will always be in last position
  • lgekman
    lgekman over 4 years
    Typo; shall be "ip -j link show"