Home / Alt manpages / pbmlife(1)

  • pbmlife(1)
  • User command
  • linux

Advance a PBM Life Pattern One Generation with pbmlife

pbmlife is Netpbm's odd little surprise: it runs one generation of Conway's Game of Life over a PBM image. You will read a pattern in, advance it, and write the next generation out without touching the original file.

Allow about ten minutes. You need Netpbm 2:11.05.02-1.1build1 or a compatible installation, a shell, and a PBM file you are willing to experiment on. An ordinary user account is enough; none of this needs sudo.

Checkpoint

This guide advances one generation only. Running the command again advances the result again, so keep each generation in its own file while you are checking a pattern.

1. Confirm the installed command

Check which executable will run and record the package version. Both of these are read-only:

$ command -v pbmlife
/usr/bin/pbmlife
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1

The installed manual describes pbmlife [pbmfile]. That optional file argument selects the input; leave it out and the program reads standard input instead. There are no options specific to pbmlife, though Netpbm's common options are recognised. Do not assume a flag from some other image utility applies here.

2. Keep a source image and choose a new destination

Back up the source if it matters to you, then pick a destination that does not already hold a result:

$ cp --preserve=all pattern.pbm pattern.pbm.before-life
$ pbmlife pattern.pbm > pattern.pbm.next

The first command changes state, since it creates a backup, but the original stays untouched throughout. The second writes the transformed image to a new file. Shell redirection truncates an existing destination before pbmlife even gets a chance to report an error, so never point > at the only copy of an image you care about.

Checkpoint

If the command exits non-zero, inspect the error and keep pattern.pbm as-is. If the new file comes out incomplete, remove only that disposable output after checking the path, then rerun to a fresh name. Restore the backup with cp --preserve=all pattern.pbm.before-life pattern.pbm if you deliberately need to undo a replacement.

3. Test a small blinker

A three-cell line is a handy smoke test. In PBM, 1 is black and 0 is white, but the pbmlife manual states the Life interpretation the other way round: a white pixel is a live beastie and a black pixel is empty space. So this test puts live cells in the zero-valued pixels:

$ printf '%s\n' \
  'P1' \
  '5 5' \
  '1 1 1 1 1' \
  '1 1 1 1 1' \
  '1 0 0 0 1' \
  '1 1 1 1 1' \
  '1 1 1 1 1' | pbmlife | pbmtoascii -1
MM"MM
MM MM
"""""

pbmtoascii -1 is only a terminal preview here, not part of what pbmlife itself does, and the output above wraps vertically because the preview maps two image rows to each character. What matters is that the pipeline exits cleanly and the middle row changes orientation after one generation. No pbmtoascii installed? Save the output as a PBM and check it with an image viewer or another PBM-aware Netpbm utility instead.

4. Read from standard input when composing a pipeline

Pass a file path as the only positional argument. For generated or previously filtered PBM data, drop the argument and pipe the data straight in:

$ pbmlife pattern.pbm > pattern.pbm.next
$ some-pbm-producing-command | pbmlife > generated-next.pbm
$ file generated-next.pbm
generated-next.pbm: Netpbm image data, size 5 x 5, rawbits

The exact file description depends on the dimensions and encoding, but the result always stays PBM. A successful exit status means the program finished its conversion; it does not prove the pattern is the one you intended, so check dimensions and preview the result before it goes into a later pipeline.

5. Handle failures without guessing

A missing input path is just a normal file error, not a reason to reach for elevated privileges:

$ pbmlife /path/to/missing.pbm > next.pbm
pbmlife: Unable to open file '/path/to/missing.pbm' for reading.  fopen() returns errno 2 (No such file or directory)
$ printf 'exit status: %s\n' "$?"
exit status: 1

If this happens, check the path and readability without changing permissions:

$ ls -l /path/to/pattern.pbm
$ test -r /path/to/pattern.pbm && echo readable

Also confirm the input really is PBM, and that its dimensions match what the producer claims. Do not use sudo to paper over an incorrect path or to force a write into a protected destination; if that directory genuinely belongs to a service or another user, follow that system's proper change process instead of widening permissions.

6. Repeat generations safely

To advance several generations, chain distinct names so each step can be compared or thrown away on its own:

$ pbmlife pattern.pbm > pattern.g01.pbm
$ pbmlife pattern.g01.pbm > pattern.g02.pbm
$ pbmlife pattern.g02.pbm > pattern.g03.pbm

Each invocation applies exactly one generation. That is easier to audit than repeatedly overwriting one file, and it leaves you a recovery point if a later step fails. Once the final image checks out and you no longer need an intermediate, remove only the named disposable files: never delete the original as part of an unattended one-liner.

Done means

  • You confirmed pbmlife is the intended executable and know its installed version.
  • You advanced a PBM input by exactly one generation per invocation.
  • The original image stayed put while output went to a separate path.
  • You can use both file input and standard-input pipelines.
  • The output was checked as PBM data and, where useful, previewed independently.
  • Missing files and output errors get handled without reaching for extra privileges.