╔╦╗╔═╗╦ ╦╔╗ ╦ ╔═╗ ║║║ ║║ ║╠╩╗║ ║╣ ═╩╝╚═╝╚═╝╚═╝╩═╝╚═╝ ╔╦╗╦╔═╗╔╦╗╔═╗╔╗╔╔╦╗ ║║║╠═╣║║║║ ║║║║ ║║ ═╩╝╩╩ ╩╩ ╩╚═╝╝╚╝═╩╝ ╔═╗╔═╗╔═╗╦═╗╔═╗╔╦╗╔═╗╦═╗ ║ ║╠═╝║╣ ╠╦╝╠═╣ ║ ║ ║╠╦╝ ╚═╝╩ ╚═╝╩╚═╩ ╩ ╩ ╚═╝╩╚═ ============================================================================ The diamond operator has a problem. A security problem. perl script.pl 'ls |' That doesn't read a file called "ls |". It executes ls and reads its output. Oops. Enter the double diamond: <<>> Same magic as <>. Without the danger. ============================================================================ PART 1: THE PROBLEM ------------------- The regular diamond uses two-argument open internally: while (<>) # open(ARGV, $ARGV[0]) Two-argument open interprets magic characters: |command Run command, read output command| Same thing >file Open for writing (!!) +>: while (<<>>) { print; } This uses three-argument open internally: open(ARGV, '<', $ARGV[0]) The < forces read-only mode. Special characters become literal. perl script.pl 'ls |' # Now reads file literally named "ls |" .--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/ ============================================================================ PART 3: IDENTICAL BEHAVIOR -------------------------- Everything else works the same: while (<<>>) { print "$ARGV: $_"; } Multiple files: perl script.pl file1.txt file2.txt STDIN fallback: cat data.txt | perl script.pl In-place editing with -i: perl -i.bak -pe 's/old/new/g' *.txt All the diamond magic, none of the risk. ============================================================================ PART 4: THE EDGE CASE --------------------- One exception: the explicit dash for STDIN. Regular diamond: perl script.pl file1.txt - file2.txt # Works: reads file1, STDIN, file2 Double diamond before Perl 5.28: perl script.pl file1.txt - file2.txt # Error: Can't open - for reading Fixed in 5.28. Now both handle - correctly. ============================================================================ PART 5: VERSION CHECK --------------------- Double diamond requires Perl 5.22+: use v5.22; # Ensures <<>> is available while (<<>>) { # Safe input handling } For older Perls, validate @ARGV manually: 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: perl -e 'while (<<>>) { print if /pattern/ }' *.txt Clunkier than -ne, but safer. Or combine with validation: perl -e 'die if grep /\|/, @ARGV; while (<>) { print }' *.txt ============================================================================ PART 7: WHEN TO USE WHICH ------------------------- Use <<>> (double diamond) when: - Filenames come from untrusted sources - Processing user-provided file lists - Building tools for others to use - Security matters Use <> (single diamond) when: - 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: @ARGV = ('sort -n data.txt |'); while (<>) { # Reads pre-sorted data } This is a feature, not a bug. The single diamond supports it. With double diamond, you'd need explicit pipe: open my $fh, '-|', 'sort', '-n', 'data.txt'; while (<$fh>) { # Reads pre-sorted data } More verbose, but explicit. ============================================================================ PART 9: PRACTICAL MIGRATION --------------------------- Updating old scripts: # Old way (insecure) while (<>) { process($_); } # New way (secure) while (<<>>) { process($_); } One character change. That's it. ============================================================================ 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: my $text = <>. The double diamond is <<>> - two sets of angle brackets, nothing between them. <> # Double diamond Context makes it clear. In a while condition, it's double diamond. With a word after <<, it's heredoc. ============================================================================ PART 12: SUMMARY ---------------- OPERATOR SAFE? PIPES? VERSION ---------------------------------------- <> No Yes All <<>> Yes No 5.22+ The double diamond is the diamond operator for the security-conscious era. Same functionality, without the footgun. Unless you specifically need pipe expansion, use <<>>. ============================================================================ <<>> / \ << >> \ / \ / \/ SAFE Secure input since Perl 5.22 ============================================================================ japh.codes