diff --git a/AUTHORS b/AUTHORS index 032f0ae..fcae081 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,3 +13,4 @@ Kenneth Endfinger lexhuismans Ettore Simone luoling8192 +xraystyle diff --git a/README.md b/README.md index 5f0dc9f..7697eca 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,12 @@ Goal of this utility is to provide compatible CLI with [iproute2], supporting sa * `ip neigh help` * `bridge help` * `bridge link help` - * `ss help` + * `ss help` +* Options + * Brief output mode: `ip -br link` or `ip -br addr` * Link module (Interfaces) * List local interfaces `ip link` + * List interfaces in brief format `ip -br link` * Show one interface `ip link show en0` * Shutdown interface `ip link set dev en0 down` * Start interface `ip link set dev en0 up` @@ -78,6 +81,7 @@ Goal of this utility is to provide compatible CLI with [iproute2], supporting sa * IPv6 (NDP) neighbours are being flushed for all interfaces * Address module * List all addresses `ip addr` + * List all addresses in brief format `ip -br addr` * List IPv4 addresses `ip -4 addr` * List IPv6 addresses `ip -6 addr` * Add address to interface `ip addr add 10.0.0.5/24 dev en0` @@ -119,6 +123,13 @@ Goal of this utility is to provide compatible CLI with [iproute2], supporting sa * Same options work for `bridge` and `ss` commands ## Changelog +
+ HEAD + +- Added `--brief` option for show commands (https://github.com/brona/iproute2mac/issues/42, PR https://github.com/brona/iproute2mac/pull/69) + +
+
HEAD diff --git a/src/ip.py b/src/ip.py index fabdf37..cd91339 100755 --- a/src/ip.py +++ b/src/ip.py @@ -90,7 +90,7 @@ def parse_ifconfig(res, af, address): return links -def link_addr_show(argv, af, json_print, pretty_json, color, address): +def link_addr_show(argv, af, json_print, pretty_json, color, address, brief): if len(argv) > 0 and argv[0] == "dev": argv.pop(0) if len(argv) > 0: @@ -114,35 +114,62 @@ def link_addr_show(argv, af, json_print, pretty_json, color, address): return json_dump(links, pretty_json) for l in links: - print("%d: %s: <%s> mtu %d status %s" % ( - l["ifindex"], - colorize_ifname(color, l["ifname"]), - ",".join(l["flags"]), - l["mtu"], - colorize_op_state(color, l["operstate"]) - )) - print( - " link/" + l["link_type"] + - ((" " + colorize_mac(color, l["address"])) if "address" in l else "") + - ((" brd " + colorize_mac(color, l["broadcast"])) if "broadcast" in l else "") - ) - for a in l.get("addr_info", []): + if brief: + # Brief format: interface_name STATUS ip_addresses... + # Interface name (left-padded to align) + ifname_colored = colorize_ifname(color, l["ifname"]) + ifname_padding = max(0, 16 - len(l["ifname"])) + line = ifname_colored + " " * ifname_padding + " " + + # Status + status_colored = colorize_op_state(color, l["operstate"]) + status_padding = max(0, 8 - len(l["operstate"])) + line += status_colored + " " * status_padding + + # Add addresses + addrs = [] + for a in l.get("addr_info", []): + addr_str = "%s/%d" % (colorize_inet(color, a["family"], a["local"]), a["prefixlen"]) + addrs.append(addr_str) + + # For link output, show MAC address + if not address and "address" in l: + addrs.insert(0, colorize_mac(color, l["address"])) + + # Add minimum 7 spaces before first address, then single space between addresses + if addrs: + line += " " + " ".join(addrs) + print(line) + else: + print("%d: %s: <%s> mtu %d status %s" % ( + l["ifindex"], + colorize_ifname(color, l["ifname"]), + ",".join(l["flags"]), + l["mtu"], + colorize_op_state(color, l["operstate"]) + )) print( - " %s %s" % (a["family"], colorize_inet(color, a["family"], a["local"])) + - ((" peer %s" % colorize_inet(color, a["family"], a["address"])) if "address" in a else "") + - "/%d" % (a["prefixlen"]) + - ((" brd " + colorize_inet(color, a["family"], a["broadcast"])) if "broadcast" in a else "") + " link/" + l["link_type"] + + ((" " + colorize_mac(color, l["address"])) if "address" in l else "") + + ((" brd " + colorize_mac(color, l["broadcast"])) if "broadcast" in l else "") ) + for a in l.get("addr_info", []): + print( + " %s %s" % (a["family"], colorize_inet(color, a["family"], a["local"])) + + ((" peer %s" % colorize_inet(color, a["family"], a["address"])) if "address" in a else "") + + "/%d" % (a["prefixlen"]) + + ((" brd " + colorize_inet(color, a["family"], a["broadcast"])) if "broadcast" in a else "") + ) return True # Help -def do_help(argv=None, af=None, json_print=None, pretty_json=None, color=None): +def do_help(argv=None, af=None, json_print=None, pretty_json=None, color=None, brief=None): perror("Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }") perror("where OBJECT := { link | addr | route | neigh }") perror(" OPTIONS := { -V[ersion] | -j[son] | -p[retty] | -c[olor] |") - perror(" -4 | -6 }") + perror(" -br[ief] | -4 | -6 }") perror(HELP_ADDENDUM) exit(255) @@ -184,7 +211,7 @@ def do_help_neigh(): # Route Module @help_msg(do_help_route) -def do_route(argv, af, json_print, pretty_json, color): +def do_route(argv, af, json_print, pretty_json, color, brief): if not argv or ( any_startswith(["show", "lst", "list"], argv[0]) and len(argv) == 1 ): @@ -409,13 +436,13 @@ def do_route_get(argv, af, json_print, pretty_json, color): # Addr Module @help_msg(do_help_addr) -def do_addr(argv, af, json_print, pretty_json, color): +def do_addr(argv, af, json_print, pretty_json, color, brief): if not argv: argv.append("show") if any_startswith(["show", "lst", "list"], argv[0]): argv.pop(0) - return do_addr_show(argv, af, json_print, pretty_json, color) + return do_addr_show(argv, af, json_print, pretty_json, color, brief) elif "add".startswith(argv[0]) and len(argv) >= 3: argv.pop(0) return do_addr_add(argv, af) @@ -427,8 +454,8 @@ def do_addr(argv, af, json_print, pretty_json, color): return True -def do_addr_show(argv, af, json_print, pretty_json, color): - return link_addr_show(argv, af, json_print, pretty_json, color, True) +def do_addr_show(argv, af, json_print, pretty_json, color, brief): + return link_addr_show(argv, af, json_print, pretty_json, color, True, brief) def do_addr_add(argv, af): @@ -481,13 +508,13 @@ def do_addr_del(argv, af): # Link module @help_msg(do_help_link) -def do_link(argv, af, json_print, pretty_json, color): +def do_link(argv, af, json_print, pretty_json, color, brief): if not argv: argv.append("show") if any_startswith(["show", "lst", "list"], argv[0]): argv.pop(0) - return do_link_show(argv, af, json_print, pretty_json, color) + return do_link_show(argv, af, json_print, pretty_json, color, brief) elif "set".startswith(argv[0]): argv.pop(0) return do_link_set(argv, af) @@ -496,8 +523,8 @@ def do_link(argv, af, json_print, pretty_json, color): return True -def do_link_show(argv, af, json_print, pretty_json, color): - return link_addr_show(argv, af, json_print, pretty_json, color, False) +def do_link_show(argv, af, json_print, pretty_json, color, brief): + return link_addr_show(argv, af, json_print, pretty_json, color, False, brief) def do_link_set(argv, af): @@ -550,7 +577,7 @@ def do_link_set(argv, af): # Neigh module @help_msg(do_help_neigh) -def do_neigh(argv, af, json_print, pretty_json, color): +def do_neigh(argv, af, json_print, pretty_json, color, brief): if not argv: argv.append("show") @@ -694,6 +721,7 @@ def main(argv): af = -1 # default / both json_print = False pretty_json = False + brief = False color_mode = "never" while argv and argv[0].startswith("-"): @@ -706,6 +734,9 @@ def main(argv): elif argv[0] == "-4": af = 4 argv.pop(0) + elif "-brief".startswith(argv[0]): + brief = True + argv.pop(0) elif "-color".startswith(argv[0].split("=")[0]): # 'always' is default if -color is set without any value color_mode = argv[0].split("=")[1] if "=" in argv[0] else "always" @@ -738,7 +769,7 @@ def main(argv): argv.pop(0) # Functions return true or terminate with exit(255) # See help_msg and do_help* - return cmd_func(argv, af, json_print, pretty_json, color_scheme) + return cmd_func(argv, af, json_print, pretty_json, color_scheme, brief) perror('Object "{}" is unknown, try "ip help".'.format(argv[0])) exit(1) diff --git a/test/commands.sh b/test/commands.sh index 5e6e897..296a5bc 100755 --- a/test/commands.sh +++ b/test/commands.sh @@ -144,6 +144,32 @@ $ip_cmd a s ! $ip_cmd addr asdf +## brief format tests + +# Test basic -br addr show +$ip_cmd -br addr show | grep -E "^lo[0-9]* +[A-Z]+ +" + +# Test -br a shorthand +$ip_cmd -br a | grep -E "^lo[0-9]* +[A-Z]+ +" + +# Test -br with specific device +$ip_cmd -br addr show dev lo0 | grep -E "^lo0 +[A-Z]+ +" + +# Test -br with -4 (IPv4 only) +$ip_cmd -4 -br addr show | grep -E "^lo[0-9]* +[A-Z]+ +" | grep "127.0.0.1" + +# Test -br with -6 (IPv6 only) +$ip_cmd -6 -br addr show | grep -E "^lo[0-9]* +[A-Z]+ +" | grep "::1" + +# Test -br with -j (JSON output should override brief) +$ip_cmd -br -j addr show | perl -MJSON -e 'decode_json()' + +# Test order: -br before command +$ip_cmd -br addr show | grep -E "^lo[0-9]* +[A-Z]+ +" + +# Test order: -br after command (should also work) +$ip_cmd addr -br show | grep -E "^lo[0-9]* +[A-Z]+ +" + # link @@ -169,6 +195,20 @@ $ip_cmd l s | grep mtu ! $ip_cmd link asdf +## link brief format tests + +# Test basic -br link show +$ip_cmd -br link show | grep -E "^lo[0-9]* +[A-Z]+ +" + +# Test -br l shorthand +$ip_cmd -br l | grep -E "^lo[0-9]* +[A-Z]+ +" + +# Test -br with specific device +$ip_cmd -br link show lo0 | grep -E "^lo0 +[A-Z]+ +" + +# Test -br with -j (JSON output should override brief) +$ip_cmd -br -j link show | perl -MJSON -e 'decode_json()' + # neigh $ip_cmd nei help 2>&1 >/dev/null | grep "Usage: ip neighbour"