4.4 KiB
Marlin Usage Tutorial
Below is a hands-on lab you can run in a throw-away directory. It shows how Marlin’s tags give you cross-folder “links” that a plain Bash workflow can’t match without resorting to symlinks or scratch scripts.
Everything uses only the functionality that exists today (init / scan / tag
)
plus one sqlite3
query for discovery.
0 . Prep
# make a playground so we don't touch real files
mkdir -p ~/marlin_demo/{Projects/{Alpha,Beta},Media/Photos,Docs}
cd ~/marlin_demo
Create a handful of files
echo "Alpha draft" > Projects/Alpha/draft.txt
echo "Alpha final" > Projects/Alpha/final.txt
echo "Beta summary" > Projects/Beta/summary.md
echo "Budget spreadsheet" > Docs/budget.ods
echo "Scan of receipt" > Docs/receipt.pdf
echo "fake JPEG header" > Media/Photos/vacation001.jpg
echo "fake JPEG header" > Media/Photos/vacation002.jpg
1 . Initialise & scan
marlin init
marlin scan ~/marlin_demo
What happened?
Marlin walked every file under ~/marlin_demo
and upserted rows into files
.
2 . Tagging – adding cross-folder metadata
Tag Alpha project files
marlin tag "~/marlin_demo/Projects/Alpha/**/*.txt" project-alpha
Tag everything Markdown or ODS as docs
marlin tag "~/marlin_demo/**/*.md" docs
marlin tag "~/marlin_demo/**/*.ods" docs
Tag photos
marlin tag "~/marlin_demo/Media/Photos/**/*.jpg" photos
You can layer tags—vacation001.jpg
now has both photos
and (later) trip-2024
if you choose to add that.
3 . Discovering files with plain SQL
There’s no marlin search
command yet, but the DB is just SQLite:
sqlite3 ~/.local/share/marlin/index.db <<'SQL'
.headers on
.mode column
-- show all files tagged 'docs'
SELECT path
FROM files f
JOIN file_tags ft ON ft.file_id = f.id
JOIN tags t ON t.id = ft.tag_id
WHERE t.name = 'docs';
SQL
Expected output:
path
--------------------------------------------------------------
/home/user/marlin_demo/Projects/Beta/summary.md
/home/user/marlin_demo/Docs/budget.ods
Do the same for project-alpha
:
sqlite3 ~/.local/share/marlin/index.db "
SELECT path FROM files
JOIN file_tags USING(file_id)
JOIN tags USING(tag_id)
WHERE tags.name = 'project-alpha';
"
4 . Why this beats a pure Bash approach
Task | With Bash alone | With Marlin tags |
---|---|---|
Gather every Alpha file (any extension) scattered across sub-folders | find ~/Projects -path '*Alpha*' (works) but blows up if naming scheme changes |
One-time glob + marlin tag ... project-alpha , then just query by tag. |
Re-classify files later | Mass-rename or new find /grep pipeline |
marlin tag new glob or manual ad-hoc files; DB keeps history (future). |
Combine orthogonal facets e.g. “docs AND project-alpha” | Complex find piped to grep -F -f list.txt or symlink forest |
Future marlin search docs AND project-alpha (for now SQL query). |
Persist metadata when files move | Must update symlinks / scripts | Scanner sees the move (once watcher lands); tags stay attached by inode/hash. |
Think of tags as Git branches for files—cheap, many-to-many, roam across directories, and live in one place.
5 . Cleaning up
rm -rf ~/marlin_demo
sqlite3 ~/.local/share/marlin/index.db "DELETE FROM files; DELETE FROM tags; DELETE FROM file_tags;"
(or simply delete the DB file to start fresh).
Recap
- Scan every folder once.
- Tag by glob to create semantic “links.”
- Query the DB (today) or use future built-in search (soon).
Even with just these three commands, you get an index that answers questions
plain Bash would need an ever-growing tangle of find
, grep
, and symlinks to solve.