/interface print where [find name=ether2] -- not correct

Sorry about the basic question.

Why does the following command print only ether 2:

/interface print where name=ether2

but:

/interface print where [find name=ether2]

result in listing all interfaces?

Because where property of print command expects textual argument but [ find where …] provides list of interfaces in format alien to where … and print simply ignores it (try running “/interface/print where” ).

Do you mean that:

[find name=ether2] returns the .id instead of the “ether2”

How should you use [find …] with a print command?

My question originated while trying to learn better how to use the bracketed find facility.

That is:

[find ]

/interface ethernet print where name=ether2 (no find required/allowed here)

but

/interface ethernet set [find where name=ether2] comment=“this is ether2, yay!”

Is the command:

/interface ethernet set [find where name=ether2] comment=“this is ether2, yay!”

correct because

[find where name=ether2]

returns the id-number of the ethernet interface?

That is, the above command is the same as:

/interface ethernet set 1 comment=“this is ether2, yay!”

If so, is it correct to say that the use of

[find ] is applicable where the context calls for the id of the item?

Almost correct, except that there are two kinds of IDs - the internal one that stays the same as long as the object exists and is shown as *1fe or something alike (a 32-bit number in hexadecimal representation prefixed with an asterisk). These are the IDs that [find …] returns. As @mkx has already said, it actually always returns a list, try the following:
:put [/interface/ethernet/find where name~“ether”]
:put [:typeof [/interface/ethernet/find where name~“ether”]]

But even if you restrict the condition to just a single item, find … still returns a list, except that put (and many other operations) performs an automatic conversion from a single-item list (array) to a scalar:
:put [/interface/ethernet/find where name~“ether1”]
:put ([/interface/ethernet/find where name~“ether1”]->0)
:put [:typeof [/interface/ethernet/find where name~“ether1”]]

Each print assigns user-friendly aliases to the internal IDs, in the form of numbers in decimal representation; these aliases are only valid in the shell where they have been assigned and only until the next print of the same configuration branch. Try the following:
/ip/firewall/mangle/add chain=test917 dst-address=1.1.1.1 action=passthrough
/ip/firewall/mangle/add chain=test917 dst-address=2.2.2.2 action=passthrough
/ip/firewall/mangle/add chain=test917 dst-address=3.3.3.3 action=passthrough

A jump to chain test917 is (hopefully) not used anywhere in mangle, so these rules are never actually used.
Now do
/ip/firewall/mangle/print where chain=test917

  • it shows you those items numbered 0, 1, and 2.
    /ip/firewall/mangle remove 0 will remove the first one (with dst-address=1.1.1.1), but another /ip/firewall/mangle/print where chain=test917 will assign the “user-friendly ID” 0 to the first remaining one (with dst-address=2.2.2.2).

I would add that issuing “enough”:
/ip/firewall/mangle remove 0
until you get an error like “no such item” you effectively make the the mangle list empty.

EDIT: not really, see following posts

Well, this is actually a bit more complicated.

If you issue a command that refers to the user-friendly ID before you use the first print for that configuration branch, RouterOS silently assigns the user-friendly IDs the same way it would if you issued a print for that branch without specifying any conditions. But once generated, the user-friendly IDs stick to the internal ones, so if you remove the 0 once and try again without using (another) print first, you get no such item (4).

Yes, you are right, one needs a print, the loop must be #2 and #3:

  1. /ip/firewall/mangle

  2. remove 0

  3. print

The older I get the more I bump into the situation, that I believe is axiomatic, whereby everything is far far more complicated than one knows at the moment.

[admin@729hAPax3] > :put [/interface/ethernet/find where name~"ether"]
*2;*3;*4;*5;*6


[admin@729hAPax3] > :put [:typeof [/interface/ethernet/find where name~"ether"]]
array

So *2 is the “internal id,” represented as ‘asterisk followed by 32 bit number’

And the "find where name~“ether” function is always of type: array

But even if you restrict the condition to just a single item, > find … > still returns a list, except that > put > (and many other operations) performs an automatic conversion from a single-item list (array) to a scalar:
:put [/interface/ethernet/find where name~“ether1”]
:put ([/interface/ethernet/find where name~“ether1”]->0)
:put [:typeof [/interface/ethernet/find where name~“ether1”]]

And:

[admin@729hAPax3] > :put [/interface/ethernet/find where name~"ether1"]
*2

This shows the Internal ID of ether1 is *2


[admin@729hAPax3] > :put ([/interface/ethernet/find where name~"ether1"]->0)
*2

I don’t understand what the addition of “->0” does.

[admin@729hAPax3] > :put [:typeof [/interface/ethernet/find where name~"ether1"]]
array

This shows the type is still array, despite the result being a single value.


Each > print > assigns user-friendly aliases to the internal IDs, in the form of numbers in decimal representation; these aliases are only valid in the shell where they have been assigned and only until the next > print > of the same configuration branch. Try the following:
/ip/firewall/mangle/add chain=test917 dst-address=1.1.1.1 action=passthrough
/ip/firewall/mangle/add chain=test917 dst-address=2.2.2.2 action=passthrough
/ip/firewall/mangle/add chain=test917 dst-address=3.3.3.3 action=passthrough

A jump to chain > test917 > is (hopefully) not used anywhere in > mangle> , so these rules are never actually used.
Now do
/ip/firewall/mangle/print where chain=test917

  • it shows you those items numbered 0, 1, and 2.

Results:

[admin@729hAPax3] > ip/firewall/mangle/print where chain=test917
Flags: X - disabled, I - invalid; D - dynamic 
 0    chain=test917 action=passthrough dst-address=1.1.1.1 

 1    chain=test917 action=passthrough dst-address=2.2.2.2 

 2    chain=test917 action=passthrough dst-address=3.3.3.3

This shows the user-friendly version of the Internal ID. I assume it takes the form of a base-10 whole number?

/ip/firewall/mangle remove 0 > will remove the first one (with > dst-address=1.1.1.1> ), but another > /ip/firewall/mangle/print where chain=test917 > will assign the “user-friendly ID” 0 to the first remaining one (with > dst-address=2.2.2.2> ).

I certainly could be doing something wrong, but I don’t think it is working like that for me.

[admin@729hAPax3] > /ip/firewall/mangle remove 0
[admin@729hAPax3] > /ip/firewall/mangle remove 0
no such item (4)
[admin@729hAPax3] > ip/firewall/mangle/print where chain=test917
Flags: X - disabled, I - invalid; D - dynamic 
 1    chain=test917 action=passthrough dst-address=2.2.2.2 

 2    chain=test917 action=passthrough dst-address=3.3.3.3 
[admin@729hAPax3] > /ip/firewall/mangle remove 0
no such item (4)
[admin@729hAPax3] >
[admin@729hAPax3] > ip/firewall/mangle/print where chain=test917
Flags: X - disabled, I - invalid; D - dynamic 
 1    chain=test917 action=passthrough dst-address=2.2.2.2 

 2    chain=test917 action=passthrough dst-address=3.3.3.3

Issuing: “/ip/firewall/mangle remove 0” appears to remove the 1.1.1.1 rule.

Issuing: “/ip/firewall/mangle remove 0” again results in “no such item” (as expected).

Issuing: “/ip/firewall/mangle/print where chain=test917” shows friendly IDs as “1” and “2”

Issuing: “/ip/firewall/mangle remove 0” results in “no such item”

Issuing: “/ip/firewall/mangle/print where chain=test917” confirming that the the only remaining rules has IDs of “1” and 2"

Try with print without the where condition.
It should “refresh” the list and re-number the items.

Or maybe it has changed in the whatever (recent) version of Ros you are running? :confused:

A list is implicitly also an array indexed by integers starting from 0. So ($thisList->0) is a reference to the first (“zeroth”) element of thisList. To make it even crazier, you can mix different types of indice in the same array, more to find in the scripting documentation.


It’s not you, it’s the developers who keep “making it even better”. I have specially tested it on ROS 7.16.2 before posting and it worked the same like in ROS 6, i.e. the user-friendly IDs were assigned from scratch with each print. I have double-checked just now:
[me@myTik] > ip firewall/mangle/add action=passthrough chain=test

[me@myTik] > ip firewall/mangle/add action=passthrough chain=test

[me@myTik] > ip firewall/mangle/print chain=test
Flags: X - disabled, I - invalid; D - dynamic
0 chain=test action=passthrough
1 chain=test action=passthrough

[me@myTik] > ip firewall/mangle/remove 0

[me@myTik] > ip firewall/mangle/print chain=test
Flags: X - disabled, I - invalid; D - dynamic
0 chain=test action=passthrough

So the bottom line is never the user-friendly IDs without using print right before.

@all
do not mix IDs and (print) line number.
if you write remove X is readed as remove number=X
If X is one ID, is directly removed,
If X is one number, is internally converted in one ID first, based on latest “print”



false



I’ll start by saying that what you wrote in the OP doesn’t make sense, and it doesn’t work that way.

/interface print where [find name=ether2]
is equal to write

/interface print where ([:tobool [/interface find where name="ether2"]] = true)

“where” accept true and false, and RouterOS try to convert the result of “find” that is one array that contain the ether2 id to one boolean value,
and is true because is not 0, empty, nothing or nil
so the final result (because ether2 exist) is:

/interface print where (true = true)

For the same reason, if you use unexistant interface, you got nothing:

/interface print where [find name=ether666]

The correct way to write something relevant is:

/interface print where name="ether2"

And I conclude with these bizarre, but valid ways, just for fun:

/interface print where .id=[find where name="ether2"]

/interface print where name=[get [find where name="ether2"] name]

... and how are you going to conclude ? :open_mouth: :laughing:

Leave me the time to check and finish the post… :sunglasses: :laughing:

You are not as fast as you used to be ... :wink: :laughing:

Well, ~11 years on 25th have passed since 2014… and I’m not a native English speaker… :unamused:

My statement was based on the last part of last sentence:


Did you try it? When I tried it, it printed out all interfaces ... so how do you put it in your extensive explanation about boolean arithmetics (other than "NULL is true" logic)?

Do error, is not valid. You add a space after where for sure (or more probably you remove all characters of a previous command but not the space).


Simply compiler do error if where is not followed by something, and ignore it if is followed with a space....

on this line is NOT present anything after where:

> /interface print where
expected end of command (line 1 column 18)

on this line is present one space after where:

> /interface print where
Flags: R - RUNNING
Columns: NAME, TYPE, ACTUAL-MTU, L2MTU, MAC-ADDRESS

NAME TYPE ACTUAL-MTU L2MTU MAC-ADDRESS

0 R ether1 ether 1500 00:0C:29:DE:AD:BE
1 R bri-pppoe-test bridge 1500 65535 00:0C:29:DE:AD:EF
2 R lo loopback 65536 00:00:00:00:00:00

> :put [:parse "/interface print where"]
expected end of command (line 1 column 18)

> :put [:parse "/interface print where "]
7.16.2: (evl /interface/print)
6.48.7: (eval /interface print)
[code2]

Very cool!

7.17.2:

[admin@729hAPax3] > /interface print where   
expected end of command (line 1 column 18)
[admin@729hAPax3] > 
[admin@729hAPax3] > /interface print where 
Flags: X - DISABLED; R - RUNNING; S - SLAVE
Columns: NAME, TYPE, ACTUAL-MTU, L2MTU, MAX-L2MTU, MAC-ADDRESS
 #     NAME         TYPE      ACTUAL-MTU  L2MTU  MAX-L2MTU  MAC-ADDRESS      
 0  R  ether1       ether           1500   1568       9214  D4:01:C3:C0:82:CE
 1   S ether2       ether           1500   1568       9214  D4:01:C3:C0:82:CF
 2   S ether3       ether           1500   1568       9214  D4:01:C3:C0:82:D0
 3   S ether4       ether           1500   1568       9214  D4:01:C3:C0:82:D1
 4   S ether5       ether           1500   1568       9214  D4:01:C3:C0:82:D2
 5   S 2point4      wifi            1500   1560       1560  D6:01:C3:C0:82:D3
 6 X   Guest-wifi1  wifi                   1560       1560  D6:01:C3:C0:82:D6
 7 X   Guest-wifi2  wifi                   1560       1560  D6:01:C3:C0:82:D7
 8     Guest2g      wifi            1500   1560       1560  D6:01:C3:C0:82:D4
 9     Guest5g      wifi            1500   1560       1560  D6:01:C3:C0:82:D5
;;; defconf
10  R  bridge       bridge          1500   1560             D4:01:C3:C0:82:CF
11  R  lo           loopback       65536                    00:00:00:00:00:00
12   S wifi1        wifi            1500   1560       1560  D4:01:C3:C0:82:D3
13   S wifi2        wifi            1500   1560       1560  D4:01:C3:C0:82:D4
14  R  wireguard1   wg              1420                                     
[admin@729hAPax3] > 
[admin@729hAPax3] > :put [:parse "/interface print where"] 
expected end of command (line 1 column 18)
[admin@729hAPax3] > 
[admin@729hAPax3] > 
[admin@729hAPax3] > :put [:parse "/interface print where "]
(evl /interface/print)
[admin@729hAPax3] >