Filters#

This page shows the specifics of each filter.

- How to exclude filters -#

To exclude a filter, prefix the filter name with not (e.g. "not empty", "not extension": jpg, etc).

Note

If you want to exclude all filters you can set the rule's filter_mode to none.

Example:

rules:
  # using filter_mode
  - locations: ~/Desktop
    filter_mode: "none" # <- excludes all
    filters:
      - empty
      - name:
          endswith: "2022"
    actions:
      - echo: "{name}"

  # Exclude a single filter
  - locations: ~/Desktop
    filters:
      - not extension: jpg # <- matches all non-jpgs
      - name:
          startswith: "Invoice"
      - not empty # <- matches files with content
    actions:
      - echo: "{name}"

created#

Matches files / folders by created date

Parameters:
  • years (int) – specify number of years

  • months (int) – specify number of months

  • weeks (float) – specify number of weeks

  • days (float) – specify number of days

  • hours (float) – specify number of hours

  • minutes (float) – specify number of minutes

  • seconds (float) – specify number of seconds

  • mode (str) – either 'older' or 'newer'. 'older' matches files / folders created before the given time, 'newer' matches files / folders created within the given time. (default = 'older')

Returns:
  • {created} – The datetime the file / folder was created.

Examples:

Show all files on your desktop created at least 10 days ago

rules:
  - name: Show all files on your desktop created at least 10 days ago
    locations: "~/Desktop"
    filters:
      - created:
          days: 10
    actions:
      - echo: "Was created at least 10 days ago"

Show all files on your desktop which were created within the last 5 hours

rules:
  - name: Show all files on your desktop which were created within the last 5 hours
    locations: "~/Desktop"
    filters:
      - created:
          hours: 5
          mode: newer
    actions:
      - echo: "Was created within the last 5 hours"

Sort pdfs by year of creation

rules:
  - name: Sort pdfs by year of creation
    locations: "~/Documents"
    filters:
      - extension: pdf
      - created
    actions:
      - move: "~/Documents/PDF/{created.year}/"

Formatting the creation date

rules:
  - name: Display the creation date
    locations: "~/Documents"
    filters:
      - extension: pdf
      - created
    actions:
      - echo: "ISO Format:   {created.strftime('%Y-%m-%d')}"
      - echo: "As timestamp: {created.timestamp() | int}"

date_added#

Matches files by the time the file was added to a folder.

date_added is only available on macOS!

Parameters:
  • years (int) – specify number of years

  • months (int) – specify number of months

  • weeks (float) – specify number of weeks

  • days (float) – specify number of days

  • hours (float) – specify number of hours

  • minutes (float) – specify number of minutes

  • seconds (float) – specify number of seconds

  • mode (str) – either 'older' or 'newer'. 'older' matches files / folders last modified before the given time, 'newer' matches files / folders last modified within the given time. (default = 'older')

Returns:
  • {date_added} – The datetime the files / folders were added.

Works the same way as created and lastmodified.

Examples

rules:
  - name: Show the date the file was added to the folder
    locations: "~/Desktop"
    filters:
      - date_added
    actions:
      - echo: "Date added: {date_added.strftime('%Y-%m-%d')}"

duplicate#

A fast duplicate file finder.

This filter compares files byte by byte and finds identical files with potentially different filenames.

Parameters:
  • detect_original_by (str) – Detection method to distinguish between original and duplicate. Possible values are:

    • "first_seen": Whatever file is visited first is the original. This depends on the order of your location entries.
    • "name": The first entry sorted by name is the original.
    • "created": The first entry sorted by creation date is the original.
    • "lastmodified": The first file sorted by date of last modification is the original.

You can reverse the sorting method by prefixing a -.

So with detect_original_by: "-created" the file with the older creation date is the original and the younger file is the duplicate. This works on all methods, for example "-first_seen", "-name", "-created", "-lastmodified".

Returns:

{duplicate.original} - The path to the original

Examples:

Show all duplicate files in your desktop and download folder (and their subfolders)

rules:
  - name: Show all duplicate files in your desktop and download folder (and their subfolders)
    locations:
      - ~/Desktop
      - ~/Downloads
    subfolders: true
    filters:
      - duplicate
    actions:
      - echo: "{path} is a duplicate of {duplicate.original}"

Check for duplicated files between Desktop and a Zip file, select original by creation date

rules:
  - name: "Check for duplicated files between Desktop and a Zip file, select original by creation date"
    locations:
      - ~/Desktop
      - zip://~/Desktop/backup.zip
    filters:
      - duplicate:
          detect_original_by: "created"
    actions:
      - echo: "Duplicate found!"

empty#

Finds empty dirs and files

Examples:

Recursively delete empty folders

rules:
  - targets: dirs
    locations:
      - path: ~/Desktop
        max_depth: null
    filters:
      - empty
    actions:
      - delete

exif#

Filter by image EXIF data

The exif filter can be used as a filter as well as a way to get exif information into your actions.

:returns: {exif} -- a dict of all the collected exif inforamtion available in the file. Typically it consists of the following tags (if present in the file):

- ``{exif.image}`` -- information related to the main image
- ``{exif.exif}`` -- Exif information
- ``{exif.gps}`` -- GPS information
- ``{exif.interoperability}`` -- Interoperability information

Show available EXIF data of your pictures

rules:
  - name: "Show available EXIF data of your pictures"
    locations:
      - path: ~/Pictures
        max_depth: null
    filters:
      - exif
    actions:
      - echo: "{exif}"

Copy all images which contain GPS information while keeping subfolder structure:

rules:
  - name: "GPS demo"
    locations:
      - path: ~/Pictures
        max_depth: null
    filters:
      - exif: gps.gpsdate
    actions:
      - copy: ~/Pictures/with_gps/{relative_path}/

Filter by camera manufacturer

rules:
  - name: "Filter by camera manufacturer"
    locations:
      - path: ~/Pictures
        max_depth: null
    filters:
      - exif:
          image.model: Nikon D3200
    actions:
      - move: "~/Pictures/My old Nikon/"

Sort images by camera manufacturer. This will create folders for each camera model (for example "Nikon D3200", "iPhone 6s", "iPhone 5s", "DMC-GX80") and move the pictures accordingly:

rules:
  - name: "camera sort"
    locations:
      - path: ~/Pictures
        max_depth: null
    filters:
      - extension: jpg
      - exif: image.model
    actions:
      - move: "~/Pictures/{exif.image.model}/"

extension#

Filter by file extension

Parameters:
  • *extensions (list(str) or str) – The file extensions to match (does not need to start with a colon).

Returns:

  • {extension}: the original file extension (without colon)

Examples:

Match a single file extension

rules:
  - name: "Match a single file extension"
    locations: "~/Desktop"
    filters:
      - extension: png
    actions:
      - echo: "Found PNG file: {path}"

Match multiple file extensions

rules:
  - name: "Match multiple file extensions"
    locations: "~/Desktop"
    filters:
      - extension:
          - .jpg
          - jpeg
    actions:
      - echo: "Found JPG file: {path}"

Make all file extensions lowercase

rules:
  - name: "Make all file extensions lowercase"
    locations: "~/Desktop"
    filters:
      - extension
    actions:
      - rename: "{path.stem}.{extension.lower()}"

Using extension lists (yaml aliases

img_ext: &img
  - png
  - jpg
  - tiff

audio_ext: &audio
  - mp3
  - wav
  - ogg

rules:
  - name: "Using extension lists"
    locations: "~/Desktop"
    filters:
      - extension:
          - *img
          - *audio
    actions:
      - echo: "Found media file: {path}"

filecontent#

Matches file content with the given regular expression

Parameters:
  • expr (str) – The regular expression to be matched.

Any named groups ((?P<groupname>.*)) in your regular expression will be returned like this:

Returns:

  • {filecontent.groupname}: The text matched with the named group (?P<groupname>)

Examples:

Show the content of all your PDF files

rules:
  - name: "Show the content of all your PDF files"
    locations: ~/Documents
    filters:
      - extension: pdf
      - filecontent
    actions:
      - echo: "{filecontent}"

Match an invoice with a regular expression and sort by customer

rules:
  - name: "Match an invoice with a regular expression and sort by customer"
    locations: "~/Desktop"
    filters:
      - filecontent: 'Invoice.*Customer (?P<customer>\w+)'
    actions:
      - move: "~/Documents/Invoices/{filecontent.customer}/"

Exampe to filter the filename with respect to a valid date code.

The filename should start with <year>-<month>-<day>.

Regex:

  1. creates a placeholder variable containing the year
  2. allows only years which start with 20 and are followed by 2 numbers
  3. months can only have as first digit 0 or 1 and must be followed by a number
  4. days can only have 0, 1,2 or 3 and must followed by number Note: Filter is not perfect but still.
rules:
  - locations: ~/Desktop
    filters:
      - regex: '(?P<year>20\d{2})-[01]\d-[0123]\d.*'
    actions:
      - echo: "Year: {regex.year}"

hash#

Calculates the hash of a file.

Parameters:
  • algorithm (str) – Any hashing algorithm available to python's hashlib. md5 by default.

Algorithms guaranteed to be available are shake_256, sha3_256, sha1, sha3_224, sha384, sha512, blake2b, blake2s, sha256, sha224, shake_128, sha3_512, sha3_384 and md5.

Depending on your python installation and installed libs there may be additional hash algorithms to chose from.

To list the available algorithms on your installation run this in a python interpreter:

>>> import hashlib
>>> hashlib.algorithms_available
{'shake_256', 'whirlpool', 'mdc2', 'blake2s', 'sha224', 'shake_128', 'sha3_512', 'sha3_224', 'sha384', 'md5', 'sha1', 'sha512_256', 'blake2b', 'sha256', 'sha512_224', 'ripemd160', 'sha3_384', 'md4', 'sm3', 'sha3_256', 'md5-sha1', 'sha512'}

Returns:

  • {hash}: The hash of the file.

Examples:

Show the hashes of your files:

rules:
  - name: "Show the hashes and size of your files"
    locations: "~/Desktop"
    filters:
      - hash
      - size
    actions:
      - echo: "{hash} {size.decimal}"

lastmodified#

Matches files by last modified date

Parameters:
  • years (int) – specify number of years

  • months (int) – specify number of months

  • weeks (float) – specify number of weeks

  • days (float) – specify number of days

  • hours (float) – specify number of hours

  • minutes (float) – specify number of minutes

  • seconds (float) – specify number of seconds

  • mode (str) – either 'older' or 'newer'. 'older' matches files / folders last modified before the given time, 'newer' matches files / folders last modified within the given time. (default = 'older')

Returns:
  • {lastmodified} – The datetime the files / folders was lastmodified.

Examples:

rules:
  - name: "Show all files on your desktop last modified at least 10 days ago"
    locations: "~/Desktop"
    filters:
      - lastmodified:
          days: 10
    actions:
      - echo: "Was modified at least 10 days ago"

Show all files on your desktop which were modified within the last 5 hours:

rules:
  - locations: "~/Desktop"
    filters:
      - lastmodified:
          hours: 5
          mode: newer
    actions:
      - echo: "Was modified within the last 5 hours"

Sort pdfs by year of last modification

rules:
  - name: "Sort pdfs by year of last modification"
    locations: "~/Documents"
    filters:
      - extension: pdf
      - lastmodified
    actions:
      - move: "~/Documents/PDF/{lastmodified.year}/"

Formatting the last modified date

rules:
  - name: Formatting the lastmodified date
    locations: "~/Documents"
    filters:
      - extension: pdf
      - lastmodified
    actions:
      - echo: "ISO Format:   {lastmodified.strftime('%Y-%m-%d')}"
      - echo: "As timestamp: {lastmodified.timestamp() | int}"

mimetype#

Filter by MIME type associated with the file extension.

Supports a single string or list of MIME type strings as argument. The types don't need to be fully specified, for example "audio" matches everything from "audio/midi" to "audio/quicktime".

You can see a list of known MIME types on your system by running this oneliner:

python3 -c "import mimetypes as m; print('\n'.join(sorted(set(m.common_types.values()) | set(m.types_map.values()))))"
Parameters:
  • *mimetypes (list(str) or str) – The MIME types to filter for.

Returns:

  • {mimetype}: The MIME type of the file.

Examples:

Show MIME types

rules:
  - name: "Show MIME types"
    locations: "~/Downloads"
    filters:
      - mimetype
    actions:
      - echo: "{mimetype}"

Filter by 'image' mimetype

rules:
  - name: "Filter by 'image' mimetype"
    locations: "~/Downloads"
    filters:
      - mimetype: image
    actions:
      - echo: "This file is an image: {mimetype}"

Filter by specific MIME type

rules:
  - name: Filter by specific MIME type
    locations: "~/Desktop"
    filters:
      - mimetype: application/pdf
    actions:
      - echo: "Found a PDF file"

Filter by multiple specific MIME types

rules:
  - name: Filter by multiple specific MIME types
    locations: "~/Music"
    filters:
      - mimetype:
          - application/pdf
          - audio/midi
    actions:
      - echo: "Found Midi or PDF."

name#

Match files and folders by name

Parameters:
  • match (str) – A matching string in simplematch-syntax

  • startswith (str) – The filename must begin with the given string

  • contains (str) – The filename must contain the given string

  • endswith (str) – The filename (without extension) must end with the given string

  • case_sensitive (bool) – By default, the matching is case sensitive. Change this to False to use case insensitive matching.

Examples:

Match all files starting with 'Invoice':

rules:
  - locations: "~/Desktop"
    filters:
      - name:
          startswith: Invoice
    actions:
      - echo: "This is an invoice"

Match all files starting with 'A' end containing the string 'hole' (case insensitive):

rules:
  - locations: "~/Desktop"
    filters:
      - name:
          startswith: A
          contains: hole
          case_sensitive: false
    actions:
      - echo: "Found a match."

Match all files starting with 'A' or 'B' containing '5' or '6' and ending with '_end':

rules:
  - locations: "~/Desktop"
    filters:
      - name:
          startswith:
            - "A"
            - "B"
          contains:
            - "5"
            - "6"
          endswith: _end
          case_sensitive: false
    actions:
      - echo: "Found a match."

python#

Use python code to filter files.

Parameters:
  • code (str) – The python code to execute. The code must contain a return statement.

Returns:

  • If your code returns False or None the file is filtered out, otherwise the file is passed on to the next filters.
  • {python} contains the returned value. If you return a dictionary (for example return {"some_key": some_value, "nested": {"k": 2}}) it will be accessible via dot syntax in your actions: {python.some_key}, {python.nested.k}.

Examples:

rules:
  - name: A file name reverser.
    locations: ~/Documents
    filters:
      - extension
      - python: |
          return {"reversed_name": path.stem[::-1]}
    actions:
      - rename: "{python.reversed_name}.{extension}"

A filter for odd student numbers. Assuming the folder ~/Students contains the files student-01.jpg, student-01.txt, student-02.txt and student-03.txt this rule will print "Odd student numbers: student-01.txt" and "Odd student numbers: student-03.txt"

rules:
  - name: "Filter odd student numbers"
    locations: ~/Students/
    filters:
      - python: |
          return int(path.stem.split('-')[1]) % 2 == 1
    actions:
      - echo: "Odd student numbers: {path.name}"

Advanced usecase. You can access data from previous filters in your python code. This can be used to match files and capturing names with a regular expression and then renaming the files with the output of your python script.

rules:
  - name: "Access placeholders in python filter"
    locations: files
    filters:
      - extension: txt
      - regex: (?P<firstname>\w+)-(?P<lastname>\w+)\..*
      - python: |
          emails = {
              "Betts": "dbetts@mail.de",
              "Cornish": "acornish@google.com",
              "Bean": "dbean@aol.com",
              "Frey": "l-frey@frey.org",
          }
          if regex.lastname in emails: # get emails from wherever
              return {"mail": emails[regex.lastname]}
    actions:
      - rename: "{python.mail}.txt"

Result:

  • Devonte-Betts.txt becomes dbetts@mail.de.txt
  • Alaina-Cornish.txt becomes acornish@google.com.txt
  • Dimitri-Bean.txt becomes dbean@aol.com.txt
  • Lowri-Frey.txt becomes l-frey@frey.org.txt
  • Someunknown-User.txt remains unchanged because the email is not found

regex#

Matches filenames with the given regular expression

Parameters:
  • expr (str) – The regular expression to be matched.

Returns:

Any named groups in your regular expression will be returned like this:

  • {regex.groupname}: The text matched with the named group (?P<groupname>.*)

Examples:

Match an invoice with a regular expression:

rules:
  - locations: "~/Desktop"
    filters:
      - regex: '^RG(\d{12})-sig\.pdf$'
    actions:
      - move: "~/Documents/Invoices/1und1/"

Match and extract data from filenames with regex named groups: This is just like the previous example but we rename the invoice using the invoice number extracted via the regular expression and the named group the_number.

rules:
  - locations: ~/Desktop
    filters:
      - regex: '^RG(?P<the_number>\d{12})-sig\.pdf$'
    actions:
      - move: ~/Documents/Invoices/1und1/{regex.the_number}.pdf

size#

Matches files and folders by size

Parameters:
  • *conditions (list(str) or str) – The size constraints.

Accepts file size conditions, e.g: ">= 500 MB", "< 20k", ">0", "= 10 KiB".

It is possible to define both lower and upper conditions like this: ">20k, < 1 TB", ">= 20 Mb, <25 Mb". The filter will match if all given conditions are satisfied.

  • Accepts all units from KB to YB.
  • If no unit is given, kilobytes are assumend.
  • If binary prefix is given (KiB, GiB) the size is calculated using base 1024.

Returns:

  • {size.bytes}: (int) Size in bytes
  • {size.traditional}: (str) Size with unit (powers of 1024, JDEC prefixes)
  • {size.binary}: (str) Size with unit (powers of 1024, IEC prefixes)
  • {size.decimal}: (str) Size with unit (powers of 1000, SI prefixes)

Examples:

Trash big downloads:

rules:
  - locations: "~/Downloads"
    targets: files
    filters:
      - size: "> 0.5 GB"
    actions:
      - trash

Move all JPEGS bigger > 1MB and <10 MB. Search all subfolders and keep the original relative path.

rules:
  - locations:
      - path: "~/Pictures"
        max_depth: null
    filters:
      - extension:
          - jpg
          - jpeg
      - size: ">1mb, <10mb"
    actions:
      - move: "~/Pictures/sorted/{relative_path}/"