Repository: conan-io/conan
Pull request #11443 (2022-06-13 09:16:52)

New rm by pattern tool
Changelog: Feature: Added tool `rm` at `conan.tools.files` to remove files by pattern in a folder.
Docs: https://github.com/conan-io/docs/pull/XXXX

Inspired by the `remove_files_by_mask` from the old tools.


Patch:
diff --git a/conan/tools/files/__init__.py b/conan/tools/files/__init__.py
index 01f5d8c67..2d9b32036 100644
--- a/conan/tools/files/__init__.py
+++ b/conan/tools/files/__init__.py
@@ -1,5 +1,5 @@
-from conan.tools.files.files import load, save, mkdir, rmdir, ftp_download, download, get, rename, \
-    chdir, unzip, replace_in_file, collect_libs, check_md5, check_sha1, check_sha256
+from conan.tools.files.files import load, save, mkdir, rmdir, rm, ftp_download, download, get, \
+    rename, chdir, unzip, replace_in_file, collect_libs, check_md5, check_sha1, check_sha256
 
 from conan.tools.files.patches import patch, apply_conandata_patches
 from conan.tools.files.cpp_package import CppPackage
diff --git a/conan/tools/files/files.py b/conan/tools/files/files.py
index 4d7f1e4b2..7eca6af89 100644
--- a/conan/tools/files/files.py
+++ b/conan/tools/files/files.py
@@ -67,6 +67,16 @@ def rmdir(conanfile, path):
     _internal_rmdir(path)
 
 
+def rm(conanfile, pattern, folder, recursive=False):
+    for root, _, filenames in os.walk(folder):
+        for filename in filenames:
+            if fnmatch(filename, pattern):
+                fullname = os.path.join(root, filename)
+                os.unlink(fullname)
+        if not recursive:
+            break
+
+
 def get(conanfile, url, md5='', sha1='', sha256='', destination=".", filename="",
         keep_permissions=False, pattern=None, verify=True, retry=None, retry_wait=None,
         auth=None, headers=None, strip_root=False):


Test patch:
diff --git a/conans/test/unittests/tools/files/test_rm.py b/conans/test/unittests/tools/files/test_rm.py
new file mode 100644
index 000000000..1f63c209f
--- /dev/null
+++ b/conans/test/unittests/tools/files/test_rm.py
@@ -0,0 +1,66 @@
+import os
+
+# Check it is importable from tools
+from conan.tools.files import rm
+from conans.client.tools.files import chdir
+from conans.test.utils.test_files import temp_folder
+from conans.util.files import save_files
+
+
+def test_remove_files_by_mask_recursively():
+    tmpdir = temp_folder()
+
+    with chdir(tmpdir):
+        os.makedirs("subdir")
+        os.makedirs("dir.pdb")
+        os.makedirs(os.path.join("subdir", "deepdir"))
+
+    save_files(tmpdir, {"1.txt": "",
+                        "1.pdb": "",
+                        "1.pdb1": "",
+                        os.path.join("subdir", "2.txt"): "",
+                        os.path.join("subdir", "2.pdb"): "",
+                        os.path.join("subdir", "2.pdb1"): "",
+                        os.path.join("subdir", "deepdir", "3.txt"): "",
+                        os.path.join("subdir", "deepdir", "3.pdb"): "",
+                        os.path.join("subdir", "deepdir", "3.pdb1"): ""})
+
+    rm(None, "*.sh", tmpdir, recursive=True)
+
+    removed_files = rm(None, "*.pdb", tmpdir, recursive=True)
+
+    assert os.path.isdir(os.path.join(tmpdir, "dir.pdb"))
+
+    assert os.path.isfile(os.path.join(tmpdir, "1.txt"))
+    assert not os.path.isfile(os.path.join(tmpdir, "1.pdb"))
+    assert os.path.isfile(os.path.join(tmpdir, "1.pdb1"))
+
+    assert os.path.isfile(os.path.join(tmpdir, "subdir", "2.txt"))
+    assert not os.path.isfile(os.path.join(tmpdir, "subdir", "2.pdb"))
+    assert os.path.isfile(os.path.join(tmpdir, "subdir", "2.pdb1"))
+
+    assert os.path.isfile(os.path.join(tmpdir, "subdir", "deepdir", "3.txt"))
+    assert not os.path.isfile(os.path.join(tmpdir, "subdir", "deepdir", "3.pdb"))
+    assert os.path.isfile(os.path.join(tmpdir, "subdir", "deepdir", "3.pdb1"))
+
+    rm(None, "*.pdb", tmpdir, recursive=True)
+
+
+def test_remove_files_by_mask_non_recursively():
+    tmpdir = temp_folder()
+    with chdir(tmpdir):
+        os.makedirs("subdir")
+
+    save_files(tmpdir, {"1.txt": "",
+                        "1.pdb": "",
+                        "1.pdb1": "",
+                        os.path.join("subdir", "2.txt"): "",
+                        os.path.join("subdir", "2.pdb"): "",
+                        os.path.join("subdir", "2.pdb1"): ""})
+
+    rm(None, "*.pdb", tmpdir)
+    assert not os.path.exists(os.path.join(tmpdir, "1.pdb"))
+    assert os.path.exists(os.path.join(tmpdir, "subdir", "2.pdb"))
+
+    assert os.path.exists(os.path.join(tmpdir, "1.txt"))
+    assert os.path.exists(os.path.join(tmpdir, "subdir", "2.txt"))