1

I'm creating a script in Bash to change all MAC addresses of my PC. I can list all network interfaces with this:

ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo

And the output of the script is:

eth0
wlan0

Now I need to create a variable for each network interface (to use it in the future), but I don't know how, and Google didn't help me...

Jeffrey
  • 1,239
  • 8
  • 15
user2757192
  • 115
  • 2
  • 9

4 Answers4

3

Answer:

readarray -t interfaces < <(ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo)

echo "${interfaces[0]}" # prints eth0
echo "${interfaces[1]}" # prints wlan0


And to loop over them use for:

for curInterface in "${interfaces[@]}"; do
    echo "$curInterface"
done



But there are better ways to parse data:

First of all, instead of grepping < character you can use -o flag. This will output all of the data on single lines. Then you simply need the second word without : character. This is very simple in pure bash:

interfaces=()
while read -r _ curInterface _; do
    interfaces+=("${curInterface%:}")
done < <(ip -o link)
Aleks-Daniel Jakimenko-A.
  • 10,335
  • 3
  • 41
  • 39
  • Not quite enough. You forgot `-t` to `readarray` making it include the newlines on the array as well. Also, your other way to parse data would place it on a subshell leaving `interfaces` to no value. – konsolebox Sep 07 '13 at 15:32
  • Seems like it was your first attempt to use `readarray`? ;) I also suggest using other variables beside `_` for the sake of good practice. Bash uses that variable as well. – konsolebox Sep 07 '13 at 15:42
  • @konsolebox of course not, I have simply forgot to write it because I was testing it in a terminal and out of laziness wrote ``echo ${curInterface[0]}`` without quotes. ``echo`` successfully trimmed the string and made me think that I'm done :) How does bash use ``_`` variable? – Aleks-Daniel Jakimenko-A. Sep 07 '13 at 15:50
  • I see. http://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html -> I guess it's just an option to override the variable. I prefer using `__`. Actually I'm probably the only one who does that, unless someone copies my style :) – konsolebox Sep 07 '13 at 15:59
  • Thanks fou your help, but when I add 'readarray -t interfaces < <(ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo)' the shell give me a error: 'Syntax error: redirection unexpected' .... why¿? :( – user2757192 Sep 07 '13 at 16:18
  • @user2757192 that's because you're using ``sh`` instead of ``bash``. Change you [shebang](http://en.wikipedia.org/wiki/Shebang_%28Unix%29) from ``#!/bin/sh`` to ``#!/bin/bash``. – Aleks-Daniel Jakimenko-A. Sep 07 '13 at 16:33
  • @konsolebox well, it doesn't affect ``_`` in any way, so it is safe to use it. – Aleks-Daniel Jakimenko-A. Sep 07 '13 at 18:07
  • @Aleks-DanielJakimenko Yeah I guess that doesn't really matter in Bash. It's only in other shells where you need to have a workaround with it. – konsolebox Sep 07 '13 at 18:29
  • No, I have it in my script... :S – user2757192 Sep 07 '13 at 18:41
  • @user2757192 then how are you executing your script? Do it by ``./myscript`` Or you can even force bash by ``bash myscript``. But please prefer the first method – Aleks-Daniel Jakimenko-A. Sep 07 '13 at 18:51
  • Yes, this was de problem... I open the script with sudo sh script.sh -.-" Thnks for the reply! :) – user2757192 Sep 07 '13 at 18:57
0

You can create an array from this output, and loop through it after.

my_array=( $(ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo) )

You can also this exmaple giving different alternatives redirect output to array

Community
  • 1
  • 1
Jeremy D
  • 4,787
  • 1
  • 31
  • 38
0

Store the output in an array:

interfaces=( $(ip link | awk '/</ { print $2 }' | awk -F: '!/lo/ {print $1}') )
chepner
  • 497,756
  • 71
  • 530
  • 681
0

And I could have it simpler like this with one awk command:

readarray -t youravar < <(exec ip link | awk -F': ' '/^[0-9]+:/&&!/ lo: /{print $2}')
konsolebox
  • 72,135
  • 12
  • 99
  • 105