Bash One-liners
PERL ONE-LINERS IN BASH SCRIPTSThis page shows how to run a list of shell commands through a Perl one-liner so you get clean error handling and colored output. Bash handles the orchestration, while Perl adds text processing and reliable error reporting in a single line.
I use this pattern whenever I need to execute a batch of system commands with clear visual feedback. The trick is feeding a shell variable into a Perl one-liner that runs each command and reports the result.
Part 1: THE HEREDOC SETUP
The first step is gathering your commands into a single variable. Bash heredocs handle this cleanly, and a quoted delimiter stops the shell from expanding variables inside the block.Theread -r -d '' CMDS <<'CMDS' sudo apt install -y build-essential sudo cpanm JSON::XS CMDS
-r flag stops the shell from interpreting backslashes, and -d '' tells read to keep reading until the end of the file. After this step, the $CMDS variable holds your full command list and is ready to pipe into Perl.
Part 2: THE PERL ONE-LINER ANATOMY
The actual execution happens in this Perl command.Let us break down those flags because they are the secret sauce:echo $CMDS | perl -MTerm::ANSIColor=':constants' -nlE ' chomp; unless ( m~^$|^\#~ ) { say BOLD GREEN qq|> $_|, RESET; system $_; unless ($? == 0) { die BOLD RED qq|> Fail: $?\n|, RESET; } } '
-n Wraps your code in a while(<>) loop, processing line by line -l Handles line endings automatically (chomp on input, newline on print) -E Enables modern features like say() - think of it as -e with benefits -M Loads modules, here importing ANSI color constants
Part 3: WHAT THE SCRIPT ACTUALLY DOES
Walking through the logic:Strips the trailing newline. Withchomp;
-l this is somewhat redundant, but being explicit never hurts and makes the intent crystal clear.
Skip empty lines and comments. The tilde delimiters let us use slashes freely inside the regex. This is the kind of thoughtful touch that makes Perl one-liners maintainable.unless ( m~^$|^\#~ ) {
Print the command we are about to run in bold green. Thesay BOLD GREEN qq|> $_|, RESET;
qq|...| quoting style avoids escaping issues. Visual feedback matters when running system commands, so you want to see what is happening.
Execute the command. This is the whole point. Perl's system() hands off to the shell and waits for completion.system $_;
Check the exit status. If anything goes wrong, die in bold red with the actual exit code. No silent failures here.unless ($? == 0) { die BOLD RED qq|> Fail: $?\n|, RESET; }
Part 4: WHY THIS PATTERN WORKS
You might ask: why not just run the commands directly in bash? A few reasons:- Unified error handling - one place to catch and report failures
- Consistent formatting - every command gets the same visual treatment
- Filtering logic - easy to skip comments, blank lines, or add conditions
- The
-nloop - scales to any number of commands without extra scaffolding
This is the Perl philosophy in action: make the common case elegant and the complex case possible.
Part 5: VARIATIONS TO TRY
Dry run mode - just show what would execute:Add timing information:echo $CMDS | perl -nlE 'say "Would run: $_" unless /^$|^#/'
Log to a file while also printing:echo $CMDS | perl -MTime::HiRes=time -nlE ' next if /^$|^#/; my $start = time; system $_; printf "Took %.2fs\n", time - $start; '
CLOSING THOUGHTSecho $CMDS | perl -nlE ' next if /^$|^#/; say $_; open my $log, ">>", "commands.log"; say $log scalar(localtime) . ": $_"; system $_; '
The combination of bash's process control and Perl's text processing creates something greater than either alone. This heredoc-to-one-liner pattern has saved me countless hours when setting up new systems or running maintenance scripts.
The flags -nlE with -M for modules will cover 90% of your one-liner needs. Commit them to muscle memory and you will reach for this technique often.
perl.gg