diff --git a/Makefile.am b/Makefile.am
index baae4d0c1ee4..28437488ab93 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -74,7 +74,8 @@ ndctl_SOURCES = ndctl.c \
 		util/usage.c \
 		util/size.c \
 		util/strbuf.c \
-		util/wrapper.c
+		util/wrapper.c \
+		util/filter.c
 
 if ENABLE_TEST
 ndctl_SOURCES += test/libndctl.c \
diff --git a/builtin-xable-region.c b/builtin-xable-region.c
index d21cb984c375..82bce63fda4b 100644
--- a/builtin-xable-region.c
+++ b/builtin-xable-region.c
@@ -2,7 +2,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <limits.h>
+#include <util/filter.h>
 #include <util/parse-options.h>
 #include <ndctl/libndctl.h>
 
@@ -39,8 +39,6 @@ static const char *parse_region_options(int argc, const char **argv,
 static int do_xable_region(const char *region_arg,
 		int (*xable_fn)(struct ndctl_region *))
 {
-	unsigned long bus_id = ULONG_MAX, id;
-	const char *provider, *region_name;
 	int rc = -ENXIO, success = 0;
 	struct ndctl_region *region;
 	struct ndctl_ctx *ctx;
@@ -53,29 +51,12 @@ static int do_xable_region(const char *region_arg,
 	if (rc < 0)
 		goto out;
 
-	if (region_bus) {
-		char *end = NULL;
-
-		bus_id = strtoul(region_bus, &end, 0);
-		if (end)
-			bus_id = ULONG_MAX;
-	}
-
         ndctl_bus_foreach(ctx, bus) {
-		provider = ndctl_bus_get_provider(bus);
-		id = ndctl_bus_get_id(bus);
-
-		if (bus_id < ULONG_MAX && bus_id != id)
-			continue;
-		else if (bus_id == ULONG_MAX && region_bus
-				&& strcmp(region_bus, provider) != 0)
+		if (!util_bus_filter(bus, region_bus))
 			continue;
 
 		ndctl_region_foreach(bus, region) {
-			region_name = ndctl_region_get_devname(region);
-
-			if (strcmp(region_arg, "all") != 0
-					&& strcmp(region_arg, region_name) != 0)
+			if (!util_region_filter(region, region_arg))
 				continue;
 			if (xable_fn(region) == 0)
 				success++;
diff --git a/builtin-xaction-namespace.c b/builtin-xaction-namespace.c
index 1d7e460e0950..5eb28bbeedfc 100644
--- a/builtin-xaction-namespace.c
+++ b/builtin-xaction-namespace.c
@@ -21,6 +21,7 @@
 #include <uuid/uuid.h>
 #include <sys/types.h>
 #include <util/size.h>
+#include <util/filter.h>
 #include <ndctl/libndctl.h>
 #include <util/parse-options.h>
 #include <ccan/array_size/array_size.h>
@@ -536,11 +537,10 @@ static int namespace_reconfig(struct ndctl_region *region,
 static int do_xaction_namespace(const char *namespace,
 		enum namespace_action action)
 {
-	unsigned long bus_id = ULONG_MAX, region_id = ULONG_MAX, id;
-	const char *provider, *region_name, *ndns_name;
 	int rc = -ENXIO, success = 0;
 	struct ndctl_namespace *ndns;
 	struct ndctl_region *region;
+	const char *ndns_name;
 	struct ndctl_ctx *ctx;
 	struct ndctl_bus *bus;
 
@@ -554,40 +554,12 @@ static int do_xaction_namespace(const char *namespace,
 	if (verbose)
 		ndctl_set_log_priority(ctx, LOG_DEBUG);
 
-	if (param.bus) {
-		char *end = NULL;
-
-		bus_id = strtoul(param.bus, &end, 0);
-		if (end)
-			bus_id = ULONG_MAX;
-	}
-
-	if (param.region) {
-		char *end = NULL;
-
-		region_id = strtoul(param.region, &end, 0);
-		if (end)
-			region_id = ULONG_MAX;
-	}
-
         ndctl_bus_foreach(ctx, bus) {
-		provider = ndctl_bus_get_provider(bus);
-		id = ndctl_bus_get_id(bus);
-
-		if (bus_id < ULONG_MAX && bus_id != id)
-			continue;
-		else if (bus_id == ULONG_MAX && param.bus
-				&& strcmp(param.bus, provider) != 0)
+		if (!util_bus_filter(bus, param.bus))
 			continue;
 
 		ndctl_region_foreach(bus, region) {
-			region_name = ndctl_region_get_devname(region);
-			id = ndctl_region_get_id(region);
-
-			if (region_id < ULONG_MAX && region_id != id)
-				continue;
-			else if (region_id == ULONG_MAX && param.region
-					&& strcmp(param.region, region_name) != 0)
+			if (!util_region_filter(region, param.region))
 				continue;
 
 			if (param.type) {
diff --git a/util/filter.c b/util/filter.c
new file mode 100644
index 000000000000..8c8dbf1a8887
--- /dev/null
+++ b/util/filter.c
@@ -0,0 +1,56 @@
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <util/filter.h>
+#include <ndctl/libndctl.h>
+
+struct ndctl_bus *util_bus_filter(struct ndctl_bus *bus, const char *ident)
+{
+	char *end = NULL;
+	const char *provider;
+	unsigned long bus_id, id;
+
+	if (!ident || strcmp(ident, "all") == 0)
+		return bus;
+
+	bus_id = strtoul(ident, &end, 0);
+	if (end == ident || end[0])
+		bus_id = ULONG_MAX;
+
+	provider = ndctl_bus_get_provider(bus);
+	id = ndctl_bus_get_id(bus);
+
+	if (bus_id < ULONG_MAX && bus_id == id)
+		return bus;
+
+	if (bus_id == ULONG_MAX && strcmp(ident, provider) == 0)
+		return bus;
+
+	return NULL;
+}
+
+struct ndctl_region *util_region_filter(struct ndctl_region *region,
+		const char *ident)
+{
+	char *end = NULL;
+	const char *name;
+	unsigned long region_id, id;
+
+	if (!ident || strcmp(ident, "all") == 0)
+		return region;
+
+	region_id = strtoul(ident, &end, 0);
+	if (end == ident || end[0])
+		region_id = ULONG_MAX;
+
+	name = ndctl_region_get_devname(region);
+	id = ndctl_region_get_id(region);
+
+	if (region_id < ULONG_MAX && region_id == id)
+		return region;
+
+	if (region_id == ULONG_MAX && strcmp(ident, name) == 0)
+		return region;
+
+	return NULL;
+}
diff --git a/util/filter.h b/util/filter.h
new file mode 100644
index 000000000000..bc5c2557a65c
--- /dev/null
+++ b/util/filter.h
@@ -0,0 +1,6 @@
+#ifndef _NDCTL_FILTER_H_
+#define _NDCTL_FILTER_H_
+struct ndctl_bus *util_bus_filter(struct ndctl_bus *bus, const char *ident);
+struct ndctl_region *util_region_filter(struct ndctl_region *region,
+		const char *ident);
+#endif
