Home / Alt manpages / dpkg-parsechangelog(1)

  • dpkg-parsechangelog(1)
  • User command
  • linux

Extract Changelog Fields with dpkg-parsechangelog

dpkg-parsechangelog turns debian/changelog into fields a script can trust, so nobody has to grep it by hand again. Point it at a source tree and it will select the releases you need and hand back one field, cleanly, without you writing a single regular expression. The examples use the locally installed dpkg 1.22.6. Allow about 10 minutes if you already have a source tree, or 20 minutes if you are building a small test changelog first.

The command only reads. It parses debian/changelog (or a file you name) and writes a control-style record to standard output; it never installs a package, edits the changelog, or touches the source tree. No root needed.

Checkpoint

If all you want is the current source version, skip everything below except --show-field Version. There is no reason to scrape the formatted record for one line.

1. Read the current entry

Change to the source tree, then run the command with no options:

cd /path/to/source-tree
dpkg-parsechangelog

For a normal changelog, the first lines look like this:

Source: example-package
Version: 2.4.1-1
Distribution: unstable
Urgency: medium
Maintainer: Example Maintainer <[email protected]>
Date: Tue, 23 Sep 2026 10:15:00 +0100
Changes:
 example-package (2.4.1-1) unstable; urgency=medium
 .
   * Fix the parser boundary.

Every value comes from the newest changelog entry. A Debian-format entry opens with the source package and version, then one or more space-separated distributions and a semicolon; the change lines are indented, and the trailer carries the preparer's name, email address and date.

One trap worth flagging: Maintainer here is not the package's usual maintainer field. In changelog terms it names whoever prepared this set of changes, which can be a different person from the uploader.

2. Pull one field for a script

Use --show-field when a shell script needs a single value. The field name is never printed, so the result is safe to assign directly:

version=$(dpkg-parsechangelog --show-field Version)
printf 'source version: %s\n' "$version"

Expected output is the version, and nothing else:

2.4.1-1
  • Fields available. Source, Distribution, Urgency, Maintainer, Date and Timestamp can all be requested this way.
  • Missing or meaningless field. Check the exit status and treat an empty result as a data error. Do not quietly invent a default.
  • Dates. Date keeps the changelog date as text. Timestamp, added in dpkg 1.18.8, is seconds since the Unix epoch and much easier to compare. The local dpkg 1.22.6 provides both wherever the parser can calculate them.

3. Pick the release range

Parser options select entries from the top of the changelog, newest first. To pull the two newest entries:

dpkg-parsechangelog --count 2 --format rfc822

The rfc822 format gives each selected entry its own stanza, keeping per-entry metadata intact, which is the safer boundary for a script that must process releases one at a time:

Source: example-package
Version: 2.4.1-1
...

Source: example-package
Version: 2.4.0-1
...

The default dpkg format instead folds every selected change into one stanza, where the first entry is normally the newest and fields such as Urgency describe the whole selected range. Decide the format before you write a parser against it, not after.

Version boundaries beat a raw count when a release name matters more than a position:

# Versions later than 2.3.0, excluding 2.3.0 itself
dpkg-parsechangelog --since 2.3.0 --format rfc822

# Versions from 2.3.0 onwards, including 2.3.0
dpkg-parsechangelog --from 2.3.0 --format rfc822

# Versions up to and including 2.4.1
dpkg-parsechangelog --to 2.4.1 --format rfc822

--until is the exclusive counterpart to --from. Short aliases exist, but the long forms read better in a script someone else will maintain. --all includes every change and overrides the other range options, so do not pair it with a count and expect the count to still limit anything.

Checkpoint

Verify the range before you trust it downstream, for example:

dpkg-parsechangelog --since 2.3.0 --format rfc822 \
  | sed -n '1,16p'

4. Put older entries in chronological order

Selected entries stay in changelog order unless you add --reverse, which flips them so the oldest selected entry comes first. That matters for a release-note generator or a migration script that has to apply changes in the order they happened:

dpkg-parsechangelog --count 3 --reverse --format rfc822

With the classic dpkg format, the first output entry then becomes the oldest one in the selected set. The option only reorders output; it does not rewrite the file and it does not change what a version comparison means.

5. Parse a changelog outside the source tree

Give an explicit path with --file when the changelog is not sitting at debian/changelog:

dpkg-parsechangelog \
  --file /path/to/release-notes/changelog \
  --show-field Version

A single hyphen means standard input, which is what makes the command pipeline-friendly:

generate-changelog | dpkg-parsechangelog --file - --show-field Version

Warning

Only pipe in a complete changelog in a supported format. A partial entry, a missing trailer, or bad indentation should make the parser fail loudly, not hand your script an untrusted version string it treats as real.

Common traps

  • Wrong directory. The default is debian/changelog, not a file called CHANGELOG sitting wherever you happen to be. Use --file or move to the source-tree root.
  • Confusing output formats. The default combines every selected change into one stanza. Reach for --format rfc822 the moment you need each entry on its own.
  • Wrong boundary. --since excludes the version you name, --from includes it. Pick based on whether that release is already processed.
  • Hand-written changelog syntax. Keep the title at the left margin, indent the change details, and put exactly one leading space before the trailer. The file must be UTF-8.
  • Unsupported custom format. A format marker near the bottom can select a Dpkg::Changelog::... Perl parser. If that parser is not installed, the command errors; installing one is a packaging decision, not something to work around.

To diagnose a failed parse, run the command on its own without a pipeline, read the error on standard error, and look at the file around the first malformed entry. There is no undo, because the command never writes anything: fix the changelog or the input path, then rerun it.

Done means

  • You know the source. Whether the command is reading debian/changelog or an explicit file.
  • You picked the right format. dpkg or rfc822, matching what the consumer expects.
  • You checked the boundary. Inclusive or exclusive, on purpose.
  • The field command returns exactly what your script needs. Nothing more, nothing formatted.
  • The parser exits cleanly on the changelog you actually intend to package.