Home / Alt manpages / pathchk(1)

  • pathchk(1)
  • User command
  • linux

Check File Names Before You Ship Them with pathchk

A file name that's perfectly fine on your box can break a script on someone else's, and pathchk catches that before you find out the hard way. Use it to reject names invalid on the current system, or unsafe to carry to POSIX systems, before creating an archive, generating a manifest, or handing names to a script that runs elsewhere. Allow about ten minutes: a shell and GNU coreutils, nothing more, this only checks names and never creates, renames or deletes files.

The examples use GNU coreutils 9.4, installed here as package version 9.4-3ubuntu6.3. Treat its result as a gate for the next operation, not a repair tool.

1. Check an ordinary name

Pass one or more names as operands. A successful check is silent and returns status 0:

$ pathchk 'reports/September.txt'
$ printf '%s\n' "$?"
0

The slash separates components. pathchk checks the name itself; it doesn't require the path to exist and never inspects file contents. A name such as reports/September.txt can be checked before the directory or file is created.

Checkpoint

If a script needs the result, test the command directly rather than parsing its output:

if pathchk -- "$candidate"; then
    printf 'Name is acceptable: %s\n' "$candidate"
else
    printf 'Rejecting file name: %s\n' "$candidate" >&2
    exit 1
fi

The -- marks the end of options. Keep it whenever the name comes from a variable or another source, a value starting with a hyphen must be treated as a name, not a new option.

2. Check names against POSIX limits

Use -p, or its long form --portability together with -P, when the name will cross system boundaries:

$ pathchk -p -- 'build/output.bin'
$ printf '%s\n' "$?"
0
$ pathchk -p -- 'a-name_that-is-portable'
$ printf '%s\n' "$?"
0

The manual defines -p as checking for most POSIX systems: a portability check, not a conversion. Success doesn't rename the item, change its encoding, or make a future destination writable.

Use --portability when you want both the POSIX checks and the stricter checks from the next step:

$ pathchk --portability -- 'build/output.bin'
$ printf '%s\n' "$?"
0

Don't confuse a portable name with an existing path. If you need both guarantees, run a separate existence or access check afterwards, for example test -r -- "$candidate" for a file you intend to read. That's a different question, and it can fail even when the name is perfectly valid.

3. Reject empty names and leading hyphens

Add -P when an empty name or a component starting with - would trip up your next tool:

$ pathchk -P -- '-draft.txt'
pathchk: leading '-' in a component of file name '-draft.txt'
$ printf '%s\n' "$?"
1
$ pathchk -P -- ''
pathchk: empty file name
$ printf '%s\n' "$?"
1

-P checks for empty names and leading hyphens. The operand after -- is still a name, so the diagnostic is about the data being checked, not a misread attempt to invoke an option. Useful before handing names to utilities whose option parsing differs between implementations. The combined form is equivalent:

$ pathchk --portability -- '-draft.txt'
pathchk: leading '-' in a component of file name '-draft.txt'

Don't treat the diagnostic text as a stable machine interface. In scripts, use the exit status and log the rejected value separately, messages can vary with locale and coreutils version.

4. Validate a batch before changing anything

pathchk accepts multiple names, so validate the whole batch before starting an archive or rename operation:

$ pathchk --portability -- \
    'photos/2026-09-25.jpg' \
    'photos/meeting-notes.txt' \
    'photos/final-report.pdf'
$ printf '%s\n' "$?"
0

If any operand fails, the command reports the problem and returns non-zero. Stop the later operation, fix or exclude the bad input, then rerun the whole batch. That avoids the distraction trap of fixing one visible name while an unexamined one later fails halfway through a copy or export.

There's no elevated-privilege step here. Don't use sudo just to validate a name, running as root doesn't make a name portable and doesn't remove limits imposed by the destination filesystem or receiving program.

5. Investigate a length failure

A failure can name the relevant limit and the exact component that exceeded it:

$ pathchk -p -- 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
pathchk: limit 14 exceeded by length 31 of file name component 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'

The exact limit depends on the check being run and the system rules in force, don't copy the number from this example into a general policy. Use the diagnostic to find the offending component, shorten the name deliberately, and rerun the same command. If a generated name is involved, fix the naming rule at its source so the next batch doesn't recreate the failure.

Keep a rejected input available while debugging: pathchk never modifies it, so there's nothing to undo. If a later command already renamed or copied files, recovery belongs to that command's backup or version-control process, not to pathchk.

6. Confirm the version and options on a new host

Before relying on a detail in automation, confirm which implementation is installed:

$ pathchk --version
pathchk (GNU coreutils) 9.4

Use pathchk --help for the option summary on the host where the script will actually run. The documented options here are -p, -P, --portability, --help and --version. An implementation from another operating system may report different diagnostics or options, so don't silently assume GNU-specific behaviour when portability is the whole point of the check.

Done means

  • Checked every generated or imported name with pathchk before the operation that uses it.
  • Used -p when names must work on most POSIX systems.
  • Used -P or --portability when empty names and leading hyphens must be rejected.
  • Protected shell variables with --, and tested exit status in scripts rather than parsing diagnostics.
  • Changed nothing: no file, directory, permission or service was touched by the validation step.