Skip to main content
  1. Concetti/

Command Grouping - {}

·3 mins
Alessio Barnini
Author
Alessio Barnini
Table of Contents

Cosa fa
#

Le graffe {} raggruppano piu' comandi in un unico stdout. La pipe che segue riceve tutto l'output come se venisse da un comando solo — una connessione, tutti i dati dentro.


TL;DR
#

# Senza {}: ogni comando pipe separatamente → N connessioni
echo "riga 1" | nc localhost 30002
echo "riga 2" | nc localhost 30002

# Con {}: un solo stdout → una connessione
{
    echo "riga 1"
    echo "riga 2"
} | nc localhost 30002

La regola: {} sta dove si fanno le domande — chi riceve i dati non deve sapere quanti comandi li hanno generati.


Come funziona — il flusso
#

graph LR
    subgraph Blocco["{ } — stdout unificato"]
        C1[echo riga 1]
        C2[echo riga 2]
        C3[echo riga 3]
    end
    Blocco -->|pipe unica| NC[nc localhost 30002]
    NC --> Output[risposta server]

Lettura diagramma: Il subgraph con le graffe raggruppa tre comandi echo in un unico blocco con stdout unificato. Una sola pipe esce dal blocco verso nc. nc riceve tutte le righe come unico stdin e apre una sola connessione TCP. L'output del server torna come risposta singola.

Senza le graffe ogni echo | nc aprirebbe una connessione TCP separata. Con le graffe nc riceve un unico stdin con tutte le righe in sequenza.


Sintassi — regole obbligatorie
#

# Formato multi-riga (piu' leggibile)
{
    comando1
    comando2
    comando3
} | pipe-destinazione

# Formato inline (tutto su una riga)
{ comando1; comando2; comando3; } | pipe-destinazione
# OBBLIGATORIO inline:
# - spazio dopo {
# - spazio prima di }
# - punto e virgola dopo l'ultimo comando

Differenza con () — subshell
#

# {} — stesso processo, stesso ambiente
# le variabili definite dentro sono visibili fuori
{ x=5; echo $x; }
echo $x   # stampa 5

# () — subshell separata
# le variabili definite dentro NON sono visibili fuori
(x=5; echo $x)
echo $x   # stampa niente — x non esiste fuori

Per mandare dati a nc usa sempre {} — piu' leggero, stesso processo.


Casi d'uso
#

Brute force su una connessione sola — Bandit 24:

psw="password_bandit24"
{
    seq -f "%04g" 0 9999 | while read pin; do
        echo "$psw $pin"
    done
} | nc localhost 30002 | grep -v Wrong

Report con piu' comandi in un solo file:

{
    echo "<mark>= $(date) </mark>="
    cat /var/log/auth.log | grep "Failed"
    echo "<mark>= fine </mark>="
} > report.log

Redirect di stderr e stdout insieme da un blocco:

{
    comando_pericoloso
    altro_comando
} &> tutto.log

Il while dentro la pipe
#

Un caso speciale che confonde: il while genera righe, quelle righe diventano stdin del comando dopo la pipe:

# Il while e' dentro una pipe — il suo stdout fluisce a nc
seq 0 9999 | while read pin; do
    echo "$psw $pin"
done | nc localhost 30002

Qui non servono le graffe perche' il while e' gia' dentro una pipe. Le graffe servono quando vuoi raggruppare piu' comandi distinti.


Scenario Reale
#

# Analisi log — raggruppa piu' grep in un unico output
{
    grep "Failed password" /var/log/auth.log
    grep "Invalid user" /var/log/auth.log
    grep "Connection closed" /var/log/auth.log
} | sort | uniq -c | sort -rn | head -20
# tutti i pattern di attacco SSH, ordinati per frequenza
Tip

Regola pratica: se stai per scrivere lo stesso comando di destinazione tre volte (es. | nc, | grep, >> file) per comandi diversi, fermati e usa {} — lo scrivi una volta sola.


Collegato a
#

  • standard-streams — stdout, stdin, pipe
  • netcat — destinazione tipica del raggruppamento
  • seq — generatore di sequenze usato dentro i blocchi
  • bandit-24 — caso d'uso reale
  • system — categoria

Related