{"id":28712450,"url":"https://github.com/polusai/filepattern","last_synced_at":"2026-03-03T19:03:21.077Z","repository":{"id":47408261,"uuid":"356036315","full_name":"PolusAI/filepattern","owner":"PolusAI","description":"Utility to extract metadata from a file name.","archived":false,"fork":false,"pushed_at":"2025-05-22T20:13:24.000Z","size":1076,"stargazers_count":5,"open_issues_count":0,"forks_count":8,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-06-14T23:05:51.492Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PolusAI.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-04-08T20:12:15.000Z","updated_at":"2025-05-22T20:12:58.000Z","dependencies_parsed_at":"2024-06-11T19:44:29.588Z","dependency_job_id":"778431bd-671f-4362-ba81-d8328267c97b","html_url":"https://github.com/PolusAI/filepattern","commit_stats":null,"previous_names":["labshare/filepattern"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/PolusAI/filepattern","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PolusAI%2Ffilepattern","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PolusAI%2Ffilepattern/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PolusAI%2Ffilepattern/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PolusAI%2Ffilepattern/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PolusAI","download_url":"https://codeload.github.com/PolusAI/filepattern/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PolusAI%2Ffilepattern/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259896235,"owners_count":22928331,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-14T23:05:51.924Z","updated_at":"2026-03-03T19:03:21.040Z","avatar_url":"https://github.com/PolusAI.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Filepattern\n\n[![Documentation Status](https://readthedocs.org/projects/filepattern/badge/?version=latest)](https://filepattern.readthedocs.io/en/latest/?badge=latest)\n[![PyPI](https://img.shields.io/pypi/v/filepattern)](https://pypi.org/project/filepattern/)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/filepattern)\n![Bower](https://img.shields.io/bower/l/MI)\n\nThe ``filepattern`` utility is used to store files that follow a pattern, where the pattern is analogous to a simplified regular expression. The need for\n``filepattern`` arises in situations where large amounts of data with a systematic naming convention needs to be filtered by patterns in the naming. For example, one may have\na directory containing segmented images where the name contains information such as the channel, the column value, and the row value. ``filepattern`` provides the ability to\nextract all images containing such a naming pattern, filter by the row or column value, or group files by one or more of the aforementioned variables.\n\n## Summary\n- [Read the Docs](https://filepattern.readthedocs.io/en/latest/Home.html)\n- [Install](#install)\n- [Authors](#authors)\n- [License](#license)\n- [Acknowledgments](#acknowledgments)\n\n## Install\n\n`filepattern` is both pip and conda installable by running `pip install filepattern` or `conda install filepattern -c conda-forge`\n\n## Build and Install\nAlternatively, ``filepattern`` can either be build inside a `conda` environment or independently outside of it directly from the source.\n\n### __Inside Conda__\n``filepattern`` uses a CMake build system.\nBelow is an example of how to build ``filepattern`` Python package inside a `conda` environment on Linux.\n\n```bash\ngit clone https://github.com/PolusAI/filepattern.git\ncd filepattern\nconda install -y -c conda-forge compilers --file ci-utils/envs/conda_cpp.txt --file ci-utils/envs/conda_py.txt\nCMAKE_ARGS=\"-DCMAKE_PREFIX_PATH=$CONDA_PREFIX -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX \" python -m pip install . -vv\n```\n\n### __Without Using Conda__\nTo build ``filepattern`` outside of a `conda` environment, use the following example.\n```bash\ngit clone https://github.com/PolusAI/filepattern.git\ncd filepattern\nmkdir build_dep\ncd build_dep\nbash ../ci-utils/install_prereq_linux.sh\ncd ..\nexport FILEPATTERN_DEP_DIR=./build_dep/local_install\npython -m pip install . -vv\n```\n\n### __C++ Library__\n``filepattern`` also comes with a C++ API. To build and install ``filepattern`` as a C++ library, following the steps below.\n```bash\ngit clone https://github.com/PolusAI/filepattern.git\ncd filepattern\nmkdir build\ncd build\nbash ../ci-utils/install_prereq_linux.sh\ncmake -Dfilepattern_SHARED_LIB=ON -DCMAKE_PREFIX_PATH=./local_install -DCMAKE_INSTALL_PREFIX=./local_install ../src/filepattern/cpp/\nmake -j4\nmake install\n```\nTo link ``filepattern`` with the client code, use the following CMake statements.\n```\nfind_package(filepattern REQUIRED)\ntarget_link_libraries(client_executable PRIVATE filepattern::filepattern)\n```\n\n### __Java API__\n\n```filepattern``` also supplies a Java API. To add ```filepattern``` as a dependency to a project,\nthe following can be added to the pom.xml of the maven project.\n\n```xml\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eai.polus.utils\u003c/groupId\u003e\n        \u003cartifactId\u003efilepattern\u003c/artifactId\u003e\n        \u003cversion\u003eLATEST\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\nThe Java API can also be built from source using Maven. To build the project, run\n\n```bash\ngit clone https://github.com/PolusAI/filepattern.git\ncd filepattern\nmvn clean install\n```\n\nTo build a jar instead of installing filepattern, ```mvn clean package``` can be used in place of ```mvn clean install```.\n\nFor more information of the Java API, see the [Java API documentation](https://filepattern.readthedocs.io/en/latest/Java.html)\n\n\u003ch2 id=\"filepattern-section\"\u003e Filepattern \u003c/h2\u003e\n\nWhen only a path to a directory and a pattern are supplied to the constructor of ``filepattern``, ``filepattern`` will iterate over the directory, matching the filenames in the directory to the ``filepattern``. The  ``filepattern`` can either be supplied by  the user or can be found using the ``infer_pattern`` method of ``filepattern``. For example, consider a directory containing the following files,\n\n```\nimg_r001_c001_DAPI.tif\nimg_r001_c001_TXREAD.tif\nimg_r001_c001_GFP.tif\n```\n\nIn each of these filenames, there are three descriptors of the image: the row, the column, and the channel. To match these files, the pattern ``img_r{r:ddd}_c{c:ddd}_{channel:c+}`` can be used. In this pattern, the named groups are contained within the curly brackets, where the variable name is before the colon and the value is after the colon. For the value, the descriptors ``d`` and ``c`` are used, which represent a digit and a character, respectively. In the example pattern, three `d`'s are used to capture three digits. The ``+`` after ``c`` denotes that one or more characters will be captured, which is equivalent to ``[a-zA-z]+`` in a regular expression. The ``+`` symbol may be used after either ``d`` or ``c``.\n\nTo have ``filepattern`` guess what the pattern is for a directory, the static method ``infer_pattern`` can be used:\n\n```python\nimport filepattern as fp\n\npath = 'path/to/directory'\n\npattern = fp.infer_pattern(path)\n\nprint(pattern)\n\n```\nThe result is:\n\n```\nimg_r001_c001_{r:c+}.tif\n```\n\nNote that the ``infer_pattern`` can also guess the patterns from stitching vectors and text files when a path to a text file is passed, rather than a path to a directory.\n\nTo retrieve files from a directory that match the ``filepattern``, an iterator is called on the `FilePattern` object, as shown below. A user specified custom pattern, such as the one below, or the guessed pattern can be passed to the constructor.\n\n```python\nimport filepattern as fp\nimport pprint\n\nfilepath = \"path/to/directory\"\n\npattern = \"img_r{r:ddd}_c{c:ddd}_{channel:c+}.tif\"\n\nfiles = fp.FilePattern(filepath, pattern)\n\nfor file in files():\n    pprint.pprint(file)\n```\nThe output is:\n```\n({'c': 1, 'channel': 'DAPI', 'r': 1},\n ['path/to/directory/img_r001_c001_DAPI.tif'])\n({'c': 1, 'channel': 'TXREAD', 'r': 1},\n ['path/to/directory/img_r001_c001_TXREAD.tif'])\n({'c': 1, 'channel': 'GFP', 'r': 1},\n ['path/to/directory/img_r001_c001_GFP.tif'])\n```\n\nAs shown in this example, the output is a tuple where the first member is a map between the group name supplied in the pattern and the value of the group for each file name. The second member of the tuple is a vector containing the path to the matched file. The second member is stored in a vector for the case where a directory is supplied with multiple subdirectories. In this case, a third optional parameter can be passed to the constructor. If the parameter ``recursive`` is set to `True`, a recursive directory iterator will be used, which iterates over all subdirectories. If the basename of two files from two different subdirectories match, ``filepattern`` will add the path of the file to the vector in the existing tuple rather than creating a new tuple.\n\n For example, consider the directory with the structure\n\n```\n/root_directory\n    /DAPI\n        img_r001_c001.tif\n    /GFP\n        img_r001_c001.tif\n    /TXREAD\n        img_r001_c001.tif\n```\n\nIn this case, the subdirectories are split by the channel. Recursive matching can be used as shown below.\n\n```python\nimport filepattern as fp\nimport pprint\n\nfilepath = \"path/to/root/directory\"\n\npattern = \"img_r{r:ddd}_c{c:ddd}.tif\"\n\nfiles = fp.FilePattern(filepath, pattern, recursive=True)\n\nfor file in files():\n    pprint.pprint(file)\n```\n\nThe output of this case is:\n```\n({'c': 1, 'r': 1},\n ['path/to/root/directory/DAPI/img_r001_c001.tif',\n  'path/to/root/directory/GFP/img_r001_c001.tif',\n  'path/to/root/directory/TXREAD/img_r001_c001.tif'])\n```\n\n\u003ch3 id=\"floating-point\"\u003e Floating Point Support \u003c/h3\u003e\n`filepattern` has the ability to capture floating point values in file patterns. For example, if we have a set of files\n\n```\nimg_r0.05_c1.15.tif\nimg_r1.05_c2.25.tif\nimg_r2.05_c3.35.tif\n```\n\nWe can capture the values in a couple of different ways. Similar to capturing digits, the character `f` can be used to capture an element of a floating point number.\nNote that with this method, the decimal point in the number must be captured by an `f`. For example, in the file `img_r0.05_c1.15.tif`, the floating point numbers would be capture with `ffff`.\nThe code to utilize this method is\n\n```python\nfilepath = \"path/to/directory\"\n\npattern = \"img_r{r:ffff}_c{c:ffff}.tif\"\n\nfiles = fp.FilePattern(filepath, pattern)\n\nfor file in files():\n    pprint.pprint(file)\n```\n\nThe result is:\n```\n({'c': 1.15, 'r': 0.05},\n ['path/to/directory/img_r0.05_c1.15.tif'])\n({'c': 2.25, 'r': 1.05},\n ['path/to/directory/img_r1.05_c2.25.tif'])\n({'c': 3.35, 'r': 2.05},\n ['path/to/directory/img_r2.05_c3.35.tif'])\n```\n\nTo capture floating point numbers with an arbitrary number of digits, we can use `f+`. This method operates in the same way as using `d+` or `c+`, where all digits (and the decimal point) will be\ncaptured for a floating point of any length. The code for this method is\n\n```python\nfilepath = \"path/to/directory\"\n\npattern = \"img_r{r:f+}_c{c:f+}.tif\"\n\nfiles = fp.FilePattern(filepath, pattern)\n\nfor file in files():\n    pprint.pprint(file)\n```\n\nThe result of this code is the same as the previous example.\n\nThe final method for capturing floating points is to use `d` to capture the digits and to add the decimal point where needed. For example, in the file `img_r0.05_c1.15.tif`, the floating point numbers could be captured using `d.dd`. The code for this method is:\n\n```python\nfilepath = \"path/to/directory\"\n\npattern = \"img_r{r:d.dd}_c{c:d.dd}.tif\"\n\nfiles = fp.FilePattern(filepath, pattern)\n\nfor file in files():\n    pprint.pprint(file)\n```\n\nOnce again, the results are the same as the first example.\n\nNote that `d` can be used to specify even more specific floating points. For example, if we want to capturing all floating points with one digit in the whole part and an arbitrary number of digits in the decimal, we can add `d.d+` for the pattern. Similarly, this could be used in a reverse manner to capture an arbitrary number of digits in the whole part using `d+.ddd`.\n\n\u003ch3 id=\"group-by\"\u003e Group By \u003c/h3\u003e\n\nIf images need to be processed in a specific order, for example by the row number, the ``group_by`` function is used. With the directory\n\n```\nimg_r001_c001_DAPI.tif\nimg_r002_c001_DAPI.tif\nimg_r001_c001_TXREAD.tif\nimg_r002_c001_TXREAD.tif\nimg_r001_c001_GFP.tif\nimg_r002_c001_GFP.tif\n```\n\nthe images can be returned in groups where ``r`` is held constant by passing the parameter ``group_by='r'`` to the object iterator.\n\n```python\nimport filepattern as fp\nimport pprint\n\nfilepath = \"path/to/directory\"\n\npattern = \"img_r{r:ddd}_c{c:ddd}_{channel:c+}.tif\"\n\nfiles = fp.FilePattern(filepath, pattern)\n\nfor file in files(group_by='r'):\n    pprint.pprint(file)\n```\n\nThe output is:\n```\n('r': 1, [({'c': 1, 'channel': 'DAPI', 'file': 0, 'r': 1},\n  ['/home/ec2-user/Dev/FilePattern/data/example/img_r001_c001_DAPI.tif']),\n ({'c': 1, 'channel': 'TXREAD', 'file': 0, 'r': 1},\n  ['/home/ec2-user/Dev/FilePattern/data/example/img_r001_c001_TXREAD.tif']),\n ({'c': 1, 'channel': 'GFP', 'file': 0, 'r': 1},\n  ['/home/ec2-user/Dev/FilePattern/data/example/img_r001_c001_GFP.tif'])])\n('r': 2, [({'c': 1, 'channel': 'DAPI', 'file': 0, 'r': 2},\n  ['/home/ec2-user/Dev/FilePattern/data/example/img_r002_c001_DAPI.tif']),\n ({'c': 1, 'channel': 'GFP', 'file': 0, 'r': 2},\n  ['/home/ec2-user/Dev/FilePattern/data/example/img_r002_c001_GFP.tif']),\n ({'c': 1, 'channel': 'TXREAD', 'file': 0, 'r': 2},\n  ['/home/ec2-user/Dev/FilePattern/data/example/img_r002_c001_TXREAD.tif'])])\n```\nNote that the return of each call is a tuple where the first member is the ``group_by`` variable mapped to the current value and the second member is a list of files where the ``group_by`` variable matches the current value.\n\n\u003ch3 id=\"get-matching\"\u003e Get Matching \u003c/h3\u003e\n\nTo get files where the variable matches a value, the ``get_matching`` method is used. For example, if only files from the TXREAD channel are needed, ``get_matching(channel=['TXREAD']`` is called.\n\n```python\nfilepath = \"/home/ec2-user/Dev/FilePattern/data/example\"\n\npattern = \"img_r{r:ddd}_c{c:ddd}_{channel:c+}.tif\"\n\nfiles = fp.FilePattern(filepath, pattern)\n\nmatching = files.get_matching(channel=['TXREAD'])\n\npprint.pprint(matching)\n```\n\nThe output is:\n```\n[({'c': 1, 'channel': 'TXREAD', 'r': 1},\n  ['/home/ec2-user/Dev/FilePattern/data/example/img_r001_c001_TXREAD.tif']),\n ({'c': 1, 'channel': 'TXREAD', 'r': 2},\n  ['/home/ec2-user/Dev/FilePattern/data/example/img_r002_c001_TXREAD.tif'])]\n```\n\n## Text files\n``filepattern`` can also take in a text file as an input rather than a directory. To use this functionality, a path to a text file is supplied to the ``path`` variable rather than a directory. When a text file is passed as input, each line of the text file will be matched to the pattern. For example, a text file containing containing the strings\n```\nimg_r001_c001_DAPI.tif\nimg_r001_c001_TXREAD.tif\nimg_r001_c001_GFP.tif\n```\n\ncan be matched to the pattern ```img_r{r:ddd}_c{c:ddd}_{channel:c+}.tif``` with:\n\n```python\nimport filepattern as fp\nimport pprint\n\nfilepath = \"path/to/file.txt\"\n\npattern = \"img_r{r:ddd}_c{c:ddd}_{channel:c+}.tif\"\n\nfiles = fp.FilePattern(filepath, pattern)\n\nfor file in files():\n    pprint.pprint(file)\n\n```\n\nThe output is:\n\n```\n({'c': 1, 'channel': 'DAPI', 'r': 1},\n ['img_r001_c001_DAPI.tif'])\n({'c': 1, 'channel': 'TXREAD', 'r': 1},\n ['img_r001_c001_TXREAD.tif'])\n({'c': 1, 'channel': 'GFP', 'r': 1},\n ['img_r001_c001_GFP.tif'])\n```\n\n After calling ``filepattern`` on a text file,  the [group_by](#group-by) and [get_matching](#get-matching) functionality can be used the same as outlined in the [FilePattern](#filepattern-section) section.\n\n## Stitching vectors\n\n``filepattern`` can also take in stitching vectors as input. In this case, a path to a text file containing a stitching vector is passed to the ``path`` variable. A stitching vector has the following form,\n\n```\nfile: x01_y01_wx0_wy0_c1.ome.tif; corr: 0; position: (0, 0); grid: (0, 0);\nfile: x02_y01_wx0_wy0_c1.ome.tif; corr: 0; position: (3496, 0); grid: (3, 0);\nfile: x03_y01_wx0_wy0_c1.ome.tif; corr: 0; position: (6992, 0); grid: (6, 0);\nfile: x04_y01_wx0_wy0_c1.ome.tif; corr: 0; position: (10488, 0); grid: (9, 0);\n```\n\nThis stitching vector can be processed using\n\n```python\nimport filepattern as fp\n\nfilepath = 'path/to/stitching/vector.txt'\n\npattern = 'x0{x:d}_y01_wx0_wy0_c1.ome.tif'\n\nfiles = fp.FilePattern(filepath, pattern)\n\nfor file in files():\n    pprint.pprint(files)\n```\n\nThe output is:\n```\n({'correlation': 0, 'gridX': 0, 'gridY': 0, 'posX': 0, 'posY': 0, 'x': 1},\n ['x01_y01_wx0_wy0_c1.ome.tif'])\n({'correlation': 0, 'gridX': 3, 'gridY': 0, 'posX': 3496, 'posY': 0, 'x': 2},\n ['x02_y01_wx0_wy0_c1.ome.tif'])\n({'correlation': 0, 'gridX': 6, 'gridY': 0, 'posX': 6992, 'posY': 0, 'x': 3},\n ['x03_y01_wx0_wy0_c1.ome.tif'])\n({'correlation': 0, 'gridX': 9, 'gridY': 0, 'posX': 10488, 'posY': 0, 'x': 4},\n ['x04_y01_wx0_wy0_c1.ome.tif'])\n```\nAs shown in the output, ``filepattern`` not only captures the specified variables from the pattern, but also captures the variables supplied in the stitching vector.\n\n## Out of core\n\n``filepattern`` has the ability to use external memory when the dataset is too large to fit in main memory, i.e. it utilizes disk memory along with RAM. It has the same functionality as ``filepattern``, however it takes in an addition parameter called `block_size`, which limits the amount of main memory used by ``filepattern``. Consider a directory containing the files:\n\n```\nimg_r001_c001_DAPI.tif\nimg_r001_c001_TXREAD.tif\nimg_r001_c001_GFP.tif\n```\n\nThis directory can be processed with only one file in memory as:\n\n```python\nimport filepattern as fp\nimport pprint\n\nfilepath = \"path/to/directory\"\n\npattern = \"img_r{r:ddd}_c{c:ddd}_{channel:c+}.tif\"\n\nfiles = fp.FilePattern(filepath, pattern, block_size=\"125 B\")\n\n\nfor file in files():\n    pprint.pprint(file)\n\n\n```\nThe output from this example is:\n\n```\n({'c': 1, 'channel': 'DAPI', 'r': 1},\n ['/home/ec2-user/Dev/FilePattern/data/example/img_r001_c001_DAPI.tif'])\n({'c': 1, 'channel': 'TXREAD', 'r': 1},\n ['/home/ec2-user/Dev/FilePattern/data/example/img_r001_c001_TXREAD.tif'])\n({'c': 1, 'channel': 'GFP', 'r': 1},\n ['/home/ec2-user/Dev/FilePattern/data/example/img_r001_c001_GFP.tif'])\n```\nNote that the ``block_size`` argument is provided in bytes (B) in this example, but also has the options for kilobytes (KB), megabytes (MB), and gigabytes (GB). The ``block_size`` must be under 1000 GB.\n\n\u003ch3 id=\"group-by-external\"\u003e Group by and get matching\u003c/h3\u003e\n\nThe out of core version of ``filepattern`` contains the same functionalities as the in memory version. ``group_by`` is called the same way, i.e.,\n\n```python\nfor file in files(group_by=\"r\"):\n    pprint.pprint(file)\n```\n\nThe output remains identical to the in memory version.\n\nThe ``get_matching`` functionality remains the same, however the API is slightly different. In this case, ``get_matching`` is called as\n\n```python\n\nfor matching in files.get_matching(channel=['TXREAD'])\n    pprint.pprint(matching)\n```\nwhere the output is returned in blocks of `block_size`. The output is:\n\n```\n({'c': 1, 'channel': 'TXREAD', 'r': 1},\n ['/home/ec2-user/Dev/FilePattern/data/example/img_r001_c001_TXREAD.tif'])\n```\n\n## Out of Core: text files and stitching vectors\n\nOut of core processing can also be used for stitching vectors and text files. To utilize this functionality, call ``filepattern`` the same way as described previously, but add in the ``block_size`` parameter, as described in the (Out of Core)[#out-of-core] section.\n\n## Authors\n\nJesse McKinzie(Jesse.McKinzie@axleinfo.com, jesse.mckinzie@nih.gov)\nNick Schaub (nick.schaub@nih.gov, nick.schaub@labshare.org)\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE)\nCreative Commons License - see the [LICENSE](LICENSE) file for\ndetails\n\n## Acknowledgments\n\n- This utility was inspired by the notation found in the\n[MIST](https://github.com/usnistgov/MIST)\nalgorithm developed at NIST.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolusai%2Ffilepattern","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpolusai%2Ffilepattern","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolusai%2Ffilepattern/lists"}