This commit is contained in:
Ignacio Serantes
2026-05-10 16:37:46 +02:00
parent 6207cab27a
commit af21672b1c
3 changed files with 166 additions and 72 deletions

View File

@@ -14,7 +14,7 @@ __status__ = "Production"
import argparse
import json
import signal
import os
import sys
from pathlib import Path
# from baloo_tools import get_resolution
@@ -26,7 +26,7 @@ PROG_NAME = "Bagheera Search Tool"
PROG_ID = "bagheerasearch"
PROG_VERSION = __version__
PROG_BY = __author__
PROG_DATE = "2026-05-09"
PROG_DATE = "2026-05-10"
CONFIG_DIR = Path.home() / ".config" / PROG_ID
CONFIG_FILE = CONFIG_DIR / "config.json"
@@ -55,7 +55,7 @@ def save_config(config: dict) -> None:
def print_help_query() -> None:
"""Prints the detailed help for query syntax."""
help_query = f"""Help updated to 2025-01-01.
help_query = f"""{PROG_NAME} uses the Baloo search engine, which is part of the KDE ecosystem, to perform file searches so next help is obtained from Baloo documentation on 2025-01-01, with some additional information, and it may not be up to date with the latest features or changes in Baloo. For the most current information, please refer to the official Baloo documentation or resources.
Baloo offers a rich syntax for searching through your files. Certain attributes of a file can be searched through.
@@ -63,7 +63,7 @@ For example 'type' can be used to filter for files based on their general type:
type:Audio OR type:Document
The following comparison operators are supported, but note that 'not equal' (!=) operator is not available.
The following comparison operators are supported, but note that 'not equal' (!=) operator is not available in Baloo search engine.
· : - contains (only for text comparison)
· = - equal
· > - greater than
@@ -71,7 +71,7 @@ The following comparison operators are supported, but note that 'not equal' (!=)
· < - less than
· <= - less than or equal to
Currently the following types are supported:
Currently the following types, to use in --type property, are supported:
· Archive
· Folder
· Audio
@@ -90,7 +90,7 @@ The full list of properties which can be searched is listed below. They are grou
All Files
· filename
· mimetype
· modified
· modified (formated as yyyy-MM-dd[ hh[:mm[:ss]]])
· rating
· tags
· userComment
@@ -103,7 +103,7 @@ Audio
· Channels
· Comment
· Composer
· Duration
· Duration (this value must be in seconds, for example use 'duration > 300' to find files longer than 5 minutes)
· Genre
· Lyricist
· ReleaseYear
@@ -113,7 +113,7 @@ Audio
Documents
· Author
· Copyright
· CreationDate
· CreationDate (formated as yyyy-MM-dd[ hh[:mm[:ss]]])
· Generator
· Keywords
· Language
@@ -153,8 +153,44 @@ Media
· PhotoWhiteBalance
· Width
Next properties are undocumented but available in source code, may work or not, but worth trying:
· AssistiveAlternateDescription
· Arranger
· AudioCodec
· ColorSpace
· Compilation
· Conductor
· Description
· DiscNumber
· Ensemble
· Label
· License
· Location
· Lyrics
· Manufacturer
· Model
· Opus
· OriginUrl
· OriginEmailSubject
· OriginEmailSender
· OriginEmailMessageId
· Performer
· PixelFormat
· ReplayGainAlbumPeak
· ReplayGainAlbumGain
· ReplayGainTrackPeak
· ReplayGainTrackGain
· TranslationUnitsTotal
· TranslationUnitsWithTranslation
· TranslationUnitsWithDraftTranslation
· TranslationLastAuthor
· TranslationLastUpDate
· TranslationTemplateDate
· VideoCodec
{PROG_NAME} recognizes some natural language sentences in English, as long as they are capitalized, and transforms them into queries that can be interpreted by the search engine.
Baloo documentation ends here, but {PROG_NAME} adds some extra features on top of it.
Search engine recognizes some natural language sentences in English, as long as they are capitalized, and transforms them into queries that can be interpreted by the search engine.
Supported natural language sentences and patterns for queries are:
· MODIFIED TODAY
@@ -166,12 +202,18 @@ Supported natural language sentences and patterns for queries are:
<NUMBER> can be any number or a number text from ONE to TWENTY.
The --exclude and --recursive-exclude options allow you to filter files out of the results. The syntax for both options supports parentheses and logical operators (AND, OR, and NOT) to combine multiple patterns.
The --exclude and --recursive-exclude options allow you to filter files out of the results.
The syntax for both options supports parentheses and logical operators (AND, OR, and NOT) to combine multiple patterns.
In addition to standard query comparison operators, the not equal (!=) operator is available for comparing properties against specific values. Furthermore, you can compare two properties directly; for example, 'width > height' is a valid expression.
Remarks:
· All text comparison are case insensitive.
· Text comparisons are case sensitive with '==' operator but case insensitive with '=' and ':' operator. For example, 'filename:report' would match 'report.docx', 'Report.docx', and 'REPORT.docx', while 'filename=report.docx' would only match 'report.docx'.
· Tags comparisons are performed against both individual full tag string (using the '/' character as a level separator) and each individual level. All individual level values are normalized to lowercase and stripped of accents or diacritics. For example, a file tagged as 'Opera,Person/María Callas,Singer' would match any of the following elements: ['Opera', 'Person/María Callas', 'Singer', 'callas', 'maria', 'opera', 'person', 'singer']."
· Only text and numeric data are supported."""
· Only text and numeric data are supported, dates are not supported as of now.
· Baloo limit of at least three characters for property values is not applied in --exclude and --recursive-exclude options, so you can use shorter values in those options.
For example, if you have a tag named 'Science' and another one 'Science Fiction' you can't obtain only results tagged with 'Science' becouse Baloo search engine will match both 'Science' and 'Science Fiction' tags when you use 'tags:Science' in your query. To exclude results tagged with 'Science Fiction' you can use the following query:
{PROG_ID} --exclude tags:Fiction tags:Science"""
print(help_query)
@@ -183,19 +225,12 @@ def print_version() -> None:
"the good people at KDE"
)
def signal_handler(sig, frame) -> None:
"""Handles Ctrl+C gracefully."""
print("\nSearch canceled at user request.")
sys.exit(0)
def main():
parser = argparse.ArgumentParser(
description="An improved search tool for Baloo"
)
parser.add_argument("query", nargs="?", help="list of words to query for")
parser.add_argument("-d", "--directory", help="limit search to specified directory")
parser.add_argument("-d", "--directory", help="limit search to specified directory tree")
parser.add_argument("-e", "--exclude", help="Search exclude pattern")
parser.add_argument("-i", "--id", action="store_true", help="show document IDs")
parser.add_argument("-k", "--konsole", action="store_true", help="show files using file:/ and quotes")
@@ -203,7 +238,7 @@ def main():
parser.add_argument("-o", "--offset", type=int, help="offset from which to start the search")
parser.add_argument("-r", "--recursive", nargs="?", const="", default=None, help="enable recurse with or without a query")
parser.add_argument("-n", "--recursive-indent", help="recursive indent character")
parser.add_argument("-x", "--recursive-exclude", help="recursion exclude pattern")
parser.add_argument("-x", "--recursive-exclude", help="recursion exclude query")
parser.add_argument("-s", "--sort", help="sorting criteria <auto|none>")
parser.add_argument("-t", "--type", help="type of Baloo data to be searched")
parser.add_argument("-v", "--verbose", action="store_true", help="Verbose mode")
@@ -318,16 +353,30 @@ def main():
except FileNotFoundError as e:
print(e)
sys.exit(1)
except KeyboardInterrupt:
# Captura Ctrl+C dentro de main para una salida inmediata y limpia
print("\nSearch canceled at user request.")
sys.exit(0)
except BrokenPipeError:
# Silencia errores cuando se usa con 'head' o 'less' y se cierra el pipe
devnull = os.open(os.devnull, os.O_WRONLY)
os.dup2(devnull, sys.stdout.fileno())
sys.exit(1)
except Exception as e:
print(f"Error executing search: {e}")
sys.exit(1)
if __name__ == "__main__":
signal.signal(signal.SIGINT, signal_handler)
try:
main()
except KeyboardInterrupt:
# Respaldo por si la interrupción ocurre fuera del bloque principal de main
print("\nSearch canceled at user request.")
try:
sys.exit(0)
except SystemExit:
os._exit(0)
except Exception as e:
print(f"Critical error: {e}")
sys.exit(1)