NAME
Perl::Unix::Keywords - Prototype-based Unix-shaped verbs for Perl lists, trees, and subprocesses
VERSION
Version 0.01
SYNOPSIS
use strict;
use warnings;
use Perl::Unix::Keywords;
my @pm = walk {
-f $_ && /[.]pm\z/ ? $_ : ();
} 'lib';
my %by_initial = group {
substr $_, 0, 1;
} qw(apple apricot banana blueberry);
my @unique = uniq {
lc $_;
} first => qw(Foo foo BAR bar);
my %counts = uniq {
lc $_;
} count => qw(Foo foo BAR bar bar);
my $status = xargs [ $^X, '-e', 'print join qq{,}, @ARGV' ]
=> qw(one two three);
DESCRIPTION
Perl::Unix::Keywords provides four small exported functions whose prototypes allow them to be written in a keyword-like style on Perl 5.10 and later: walk, group, uniq, and xargs.
The functions are ordinary Perl subroutines. They do not install parser hooks, source filters, or new grammar. Their goal is to name four recurring operations that otherwise tend to be reconstructed from loops, hashes, callbacks, and system calls.
The design intentionally favors Perl's long-standing prototype mechanism over parameter signatures. No signature feature is required.
EXPORTS
The following names are exported by default and are also available through @EXPORT_OK:
walk group uniq xargs
PROTOTYPES
The public prototypes are:
walk (&@)
group (&@)
uniq (&$@)
xargs ($@)
The block-first forms are significant. In ordinary Perl, a & prototype can turn a literal block in that position into a code reference without requiring sub { ... } syntax.
FUNCTIONS
walk BLOCK LIST
my @files = walk {
-f $_ ? $_ : ();
} @roots;
walk performs a deterministic, depth-first, pre-order traversal of each path in LIST. Directory entries are visited in lexical order. Each visited path is placed in $_ and is also passed as the first argument to BLOCK.
The block has map-like output semantics: it may return zero, one, or several values for each visited path, and those values are flattened into the result. This makes filtering and transformation possible in one traversal:
my @perl_files = walk {
-f $_ && /[.]p[lm]\z/ ? lc($_) : ();
} 'lib', 'script';
In list context, walk returns all emitted values. In scalar context, it returns the number of emitted values.
Symbolic links are visited as entries but are never followed as directories. This avoids accidental traversal cycles. A missing root or an unreadable directory causes walk to throw an exception with croak.
group BLOCK LIST
my %groups = group {
substr $_, 0, 1;
} @items;
group computes one grouping key for each item. The item is placed in $_ and is also passed as the first argument to BLOCK. Values are retained in input order within each group.
In list context, group returns key/array-reference pairs suitable for direct assignment to a hash:
my %groups = group { length $_ } qw(a bb ccc dd);
# $groups{1} is [ 'a' ]
# $groups{2} is [ 'bb', 'dd' ]
# $groups{3} is [ 'ccc' ]
In scalar context, group returns a hash reference.
An undefined key is normalized to the empty string, matching Perl hash-key stringification in a predictable way.
uniq BLOCK MODE => LIST
my @unique = uniq { lc $_ } first => @items;
my %counts = uniq { lc $_ } count => @items;
uniq computes a canonical key for each item and supports two deliberately small modes.
firstReturn the first input item observed for each distinct canonical key, preserving first-seen order.
my @unique = uniq { lc $_ } first => qw(Foo foo BAR bar); # ('Foo', 'BAR')In scalar context,
firstreturns the number of unique representatives.countCount occurrences of each canonical key.
my %counts = uniq { lc $_ } count => qw(Foo foo BAR bar bar); # (foo => 2, bar => 3)In list context,
countreturns key/count pairs in first-seen key order. In scalar context, it returns a hash reference.
Any mode other than first or count causes an exception.
xargs COMMAND => LIST
my $status = xargs rm => @files;
my $status = xargs [ 'rm', '-f' ] => @files;
xargs lifts an in-memory Perl list into the argument vector of one external command. COMMAND may be a scalar executable name or an array reference containing an executable plus fixed leading arguments.
The command is executed with Perl's list-form system, so xargs does not construct a shell command line and does not perform shell interpolation.
xargs returns the raw value returned by system. Callers may decode it in the usual Perl fashion:
my $status = xargs command => @args;
if ($status == -1) {
die "failed to execute: $!";
}
elsif ($status & 127) {
die sprintf "terminated by signal %d", ($status & 127);
}
else {
my $exit = $status >> 8;
}
If LIST is empty, xargs performs no subprocess invocation and returns zero. The initial implementation intentionally performs a single argv-based invocation rather than reproducing every batching, delimiter, and stdin feature of the Unix xargs utility.
COMPOSITION
The functions are intended to compose as ordinary Perl list operators. For example, a tree can be traversed and the resulting files passed directly to a subprocess:
xargs rm => walk {
-f $_ && /[.]tmp\z/ ? $_ : ();
} '.';
Or values can be canonicalized before grouping:
my @unique = uniq { lc $_ } first => @names;
my %groups = group { substr lc($_), 0, 1 } @unique;
COMPATIBILITY
The distribution requires Perl 5.10 or later. The implementation uses no parameter signatures and has no non-core runtime dependencies.
DESIGN NOTES
These functions intentionally provide a small semantic core rather than clone every option of their Unix namesakes.
walkis a composable tree traversal, not a complete replacement forFile::Find.groupgroups values; it does not embed a general reducer language.uniqoffers canonical first-representative selection and counting.xargsperforms safe argv lifting for one command invocation; it does not read stdin or implement the Unix utility's batching policy.
The narrow scope is deliberate. The four operations remain orthogonal and can be combined with existing Perl constructs rather than growing into independent mini-frameworks.
DIAGNOSTICS
walk throws an exception when a requested path does not exist or a directory cannot be opened or closed.
uniq throws an exception for an unknown mode.
xargs throws an exception if its command specification is empty or is a reference type other than an array reference. Execution failure itself is reported through system's normal return value and $!.
AUTHOR
Brett Estrade (OODLER)
LICENSE AND COPYRIGHT
Copyright 2026 Brett Estrade.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.