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: |
|
---|
Returns: |
|
---|
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: |
|
---|
Returns: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
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:
- creates a placeholder variable containing the year
- allows only years which start with 20 and are followed by 2 numbers
- months can only have as first digit 0 or 1 and must be followed by a number
- 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: |
|
---|
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: |
|
---|
Returns: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
Returns:
- If your code returns
False
orNone
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 examplereturn {"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
becomesdbetts@mail.de.txt
Alaina-Cornish.txt
becomesacornish@google.com.txt
Dimitri-Bean.txt
becomesdbean@aol.com.txt
Lowri-Frey.txt
becomesl-frey@frey.org.txt
Someunknown-User.txt
remains unchanged because the email is not found
regex#
Matches filenames with the given regular expression
Parameters: |
|
---|
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: |
|
---|
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}/"