Hobby projects → Hiding sample files in Jellyfin
Guide · Jellyfin 10.11 · August 2026

Hide sample files in Jellyfin without breaking your seeds

Scene releases ship a 30-second sample clip alongside the film, and Jellyfin proudly shelves each one as a movie in its own right — a library full of posters for SAMPLE-Sky.Captain…. If those files are still seeding, you cannot delete or rename a single one without breaking the torrent. This is how we hid every sample in a large library with a handful of glob patterns and zero filesystem changes — and the audit step that stopped us from silently hiding real episodes along the way.

The constraints

What Jellyfin already ignores — and what slips through

Jellyfin has built-in ignore rules (case-insensitive) that catch the polite cases: a file named exactly sample.mkv, anything ending .sample.mkv, and a folder named sample. Usefully, these match on name, not size — we found one “sample” over 300 MB that the built-ins were already hiding correctly.

What slips through is everything else the scene has ever invented: SAMPLE-Movie.Name.mkv, Sample-002, !sample.mkv, Movie.Name.Sample.x264-GRP.mkv, movie-sample-GRP.mkv, [SAMPLE] in brackets… each one becomes a movie tile.

Dead ends first

Per-directory .ignore files. Jellyfin supports dropping an empty .ignore file into a folder to exclude it. Two problems: in the 10.11 series this feature has open bug reports for over-eager exclusion, and it excludes the whole folder — useless when the sample sits in the same directory as the real film, which is exactly where scene releases put it.

Renaming inside the torrent client. qBittorrent can rename a file internally while preserving the seed (it keeps the mapping). It works, and it is the right tool for a single stubborn file — but at library scale it is manual work per torrent, and the next download starts the cycle again.

The route that worked: pattern-based ignoring

The Jellyfin Ignore plugin adds a config page where you list glob patterns; anything matching is invisible to library scans. It matches case-insensitively, hides individual files rather than whole folders, and needs no filesystem changes at all — the seeds never know.

One trap before anything else: patterns match against the entire file path, and in the DotNet.Glob syntax the plugin uses, * does not cross directory separators. A naive *sample* therefore matches nothing at all — every pattern needs a **/ prefix to reach files deep in the tree.

Audit before you act

The step that saves you from quietly hiding real films. Run both directions of the check before saving any pattern.

A substring as common as “sample” appears in real titles. Two find commands tell you, in advance, exactly what a pattern would do: the collateral check lists large files (real films and episodes) a pattern would hide, and the escapee check lists small sample files it would miss.

On the media server — adjust the path and the size cut-off to taste
R="^sample[-_.]|^!_?sample|-sample-|\.sample\.|\.sample-|-sample\.|_sample\.|ample\]|^sample$"
echo COLLATERAL:; find /path/to/media -ipath "*sample*" -size +300M | sed "s|.*/||" | grep -iE "$R"
echo ESCAPEES:;  find /path/to/media -ipath "*sample*" -size -300M \
  \( -iname "*.mkv" -o -iname "*.mp4" -o -iname "*.avi" \) \
  | sed "s|.*/||" | grep -viE "$R" | sort -u

Our audit earned its keep immediately. A blanket **/*sample* would have hidden a Chuck episode (“…Versus the Nacho Sampler”), a Lilo & Stitch episode literally titled “Sample”, a MasterClass lesson on manipulating vocal samples, and a cooking episode with _sample_ in its filename. All real content, all gone without a word if we had saved the lazy pattern.

The patterns

Shape-based, not substring-based: each line matches a naming convention samples actually use, and nothing else.
Jellyfin → Plugins → Jellyfin Ignore → Ignore patterns
**/sample-*
**/sample-*/**
**/sample_*
**/sample_*/**
**/sample.*
**/!sample*
**/!sample*/**
**/!_sample*
**/!_sample*/**
**/*-sample.*
**/*-sample-*
**/*_sample.*
**/*.sample.*
**/*.sample-*
**/*ample].*

The odd one out, **/*ample].*, catches the [SAMPLE] bracket convention: a literal [ is awkward to express in glob syntax because it opens a character class, but an unopened ] is just a character — so we match the tail of the bracket instead.

What we deliberately left visible. No pattern for _sample_ (it appears mid-word in real episode names) and none for “ sample.mkv” with a space — that shape is shared by one genuine release sample in our library and a real episode titled “Sample”. One stray sample tile is a better outcome than one silently vanished episode. When it eventually annoys us, a single in-client rename fixes that file without touching the seed.

Finish

Save the patterns, then run a full library scan (Dashboard → Scheduled Tasks → Scan All Libraries). Existing sample entries are removed during the scan; new downloads never appear in the first place. Search your library for “sample” afterwards — it should come back close to empty.

The structural fix, for what it’s worth, is to keep downloads and library as separate trees joined by hardlinks — then the library copy can be renamed freely while the download copy seeds untouched. That is how we build new machines; this guide is for the years of library that predate the rule.