Double Diamond Operator
The diamond operator has a problem. A security problem.That doesn't read a file called "ls |". It executes ls and reads its output. Oops.perl script.pl 'ls |'
Enter the double diamond:
Same magic as <>. Without the danger.<<>>
Part 1: THE PROBLEM
The regular diamond uses two-argument open internally:Two-argument open interprets magic characters:while (<>) # open(ARGV, $ARGV[0])
Filenames with these characters become attacks:|command Run command, read output command| Same thing >file Open for writing (!!) +<file Read-write mode
That's not a file read. That's command execution.perl script.pl 'rm -rf /tmp/* |'
Part 2: THE FIX
Perl 5.22 introduced <<>>:This uses three-argument open internally:while (<<>>) { print; }
The < forces read-only mode. Special characters become literal.open(ARGV, '<', $ARGV[0])
perl script.pl 'ls |' # Now reads file literally named "ls |" .--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/
Part 3: IDENTICAL BEHAVIOR
Everything else works the same:Multiple files:while (<<>>) { print "$ARGV: $_"; }
STDIN fallback:perl script.pl file1.txt file2.txt
In-place editing with -i:cat data.txt | perl script.pl
All the diamond magic, none of the risk.perl -i.bak -pe 's/old/new/g' *.txt
Part 4: THE EDGE CASE
One exception: the explicit dash for STDIN.Regular diamond:
Double diamond before Perl 5.28:perl script.pl file1.txt - file2.txt # Works: reads file1, STDIN, file2
Fixed in 5.28. Now both handle - correctly.perl script.pl file1.txt - file2.txt # Error: Can't open - for reading
Part 5: VERSION CHECK
Double diamond requires Perl 5.22+:For older Perls, validate @ARGV manually:use v5.22; # Ensures <<>> is available while (<<>>) { # Safe input handling }
for (@ARGV) { die "Invalid filename: $_" if /[|<>]/; } while (<>) { # Now safe-ish }
Part 6: IN ONE-LINERS
The -n and -p switches still use single diamond by default.But you can use double diamond explicitly:
Clunkier than -ne, but safer.perl -e 'while (<<>>) { print if /pattern/ }' *.txt
Or combine with validation:
perl -e 'die if grep /\|/, @ARGV; while (<>) { print }' *.txt
Part 7: WHEN TO USE WHICH
Use <<>> (double diamond) when:Use <> (single diamond) when:- Filenames come from untrusted sources - Processing user-provided file lists - Building tools for others to use - Security matters
- You control the input - Quick personal scripts - You need the pipe functionality intentionally - Backwards compatibility required
Part 8: INTENTIONAL PIPES
Sometimes the pipe behavior is desired:This is a feature, not a bug. The single diamond supports it.@ARGV = ('sort -n data.txt |'); while (<>) { # Reads pre-sorted data }
With double diamond, you'd need explicit pipe:
More verbose, but explicit.open my $fh, '-|', 'sort', '-n', 'data.txt'; while (<$fh>) { # Reads pre-sorted data }
Part 9: PRACTICAL MIGRATION
Updating old scripts:One character change. That's it.# Old way (insecure) while (<>) { process($_); } # New way (secure) while (<<>>) { process($_); }
Part 10: THE NAME
Double diamond. Because there are two:Or "safe diamond." Or "three-argument diamond" (for how it works internally).<<>>
The community mostly calls it double diamond. Less confusion with the heredoc operator (which also uses <<).
Part 11: HEREDOC CONFUSION
Speaking of heredoc:That's << followed by END. Not related to <<>>.my $text = <<END; This is a heredoc. END
The double diamond is <<>> - two sets of angle brackets, nothing between them.
Context makes it clear. In a while condition, it's double diamond. With a word after <<, it's heredoc.<<END # Heredoc <<>> # Double diamond
Part 12: SUMMARY
The double diamond is the diamond operator for the security-conscious era. Same functionality, without the footgun.OPERATOR SAFE? PIPES? VERSION ---------------------------------------- <> No Yes All <<>> Yes No 5.22+
Unless you specifically need pipe expansion, use <<>>.
<<>> / \ << >> \ / \ / \/ SAFE Secure input since Perl 5.22
Created By: Wildcard Wizard. Copyright 2026