رفتن به محتوا
LoopX

pipe و ترکیب دستورها

توی این درس یاد می‌گیری قدرت اصلی لینوکس این است که دستورهای کوچک را مثل قطعه‌های لگو به هم وصل کنی. علامت | (pipe) خروجی یک دستور را به ورودی دستور بعدی می‌دهد. با چند دستور ساده، sort (مرتب‌سازی)، uniq -c (شمارش تکراری‌ها)، cut (برش ستون)، tr (تبدیل کاراکتر)، wc (شمارش) و xargs (تبدیل خروجی به argument)، کارهای تحلیلی بزرگ انجام می‌دهی. تمرین اصلی: از یک فایل لاگ وب‌سرور، ۱۰ آدرس IP پرتکرار را پیدا می‌کنی.

مسئله: یک ابزار برای همه‌چیز؟ نه!

Section titled “مسئله: یک ابزار برای همه‌چیز؟ نه!”

در بعضی سیستم‌ها هر کار یک برنامه‌ی بزرگ با دکمه‌های بی‌شمار دارد. یونیکس راه دیگری رفت: هر برنامه یک کار را خوب انجام بدهد و برنامه‌ها بتوانند خروجی‌شان را به هم بدهند. نتیجه: به‌جای ابزار «تحلیل‌گر لاگ»، چند دستور کوچک را به هم می‌چسبانی و هر سؤالی که به ذهنت برسد جواب می‌گیری، حتی سؤالی که سازنده‌ی ابزارها فکرش را نکرده بود.

تشبیه: خط تولید کارخانه

Section titled “تشبیه: خط تولید کارخانه”

کارخانه‌ی خط تولید: هر ایستگاه یک کار ساده انجام می‌دهد (برش، شست‌وشو، بسته‌بندی) و محصول را به ایستگاه بعدی می‌دهد. هر ایستگاه فقط می‌داند «ورودی‌ام چیست و خروجی‌ام چه باید باشد». pipe نوار نقاله بین ایستگاه‌هاست. و چون ایستگاه‌ها همزمان کار می‌کنند، نتیجه‌ی اول قبل از تمام شدن همه‌ی داده‌ها هم آماده می‌شود.

هر دستور stdout خود را از راه pipe به stdin دستور بعدی می‌دهد. دستورها همزمان اجرا می‌شوند (نه یکی پس از دیگری) و داده در جریان است.

برای تمرین، یک لاگ وب‌سرور نمونه (۳۰۰۰ خط، با IP های مستندسازی) می‌سازیم. (از awk فقط برای ساختن داده استفاده می‌کنم؛ در درس‌های بعد یادش می‌گیری.)

Terminal window
awk 'function rnd(n) { x = (x * 69069 + 1) % 4294967296; return int(x / 65536) % n }
BEGIN {
x = 42
split("203.0.113.5 203.0.113.5 203.0.113.5 203.0.113.5 203.0.113.5 198.51.100.7 198.51.100.7 198.51.100.7 192.0.2.44 192.0.2.44 203.0.113.9 198.51.100.23 192.0.2.8 203.0.113.77", ip, " ")
split("200 200 200 200 200 200 301 404 404 500", st, " ")
split("/index.html /about /api/users /api/orders /login /static/app.js /favicon.ico", pa, " ")
for (i = 1; i <= 3000; i++)
printf "%s - - [03/Oct/2026:12:%02d:%02d +0000] \"GET %s HTTP/1.1\" %s %d\n", ip[rnd(14) + 1], int(i / 60) % 60, i % 60, pa[rnd(7) + 1], st[rnd(10) + 1], 200 + rnd(5000)
}' > access.log
wc -l access.log
head -3 access.log
خروجی
3000 access.log
203.0.113.5 - - [03/Oct/2026:12:00:01 +0000] "GET /static/app.js HTTP/1.1" 404 3077
203.0.113.5 - - [03/Oct/2026:12:00:02 +0000] "GET /api/users HTTP/1.1" 500 3204
192.0.2.44 - - [03/Oct/2026:12:00:03 +0000] "GET /favicon.ico HTTP/1.1" 200 2811

هر خط: IP، زمان، درخواست، کد وضعیت (ستون ۹: ۲۰۰ موفق، ۴۰۴ پیدا نشد، ۵۰۰ خطای سرور) و حجم پاسخ. ستون‌ها با فاصله جدا شده‌اند.

| خروجی دستور چپ را به ورودی دستور راست می‌دهد:

Terminal window
ls /etc | head -5
echo "--- تعداد آیتم‌های /etc:"
ls /etc | wc -l
echo "--- ۳ خط وسط (خط‌های 5 تا 7):"
head -n 7 access.log | tail -n 3
خروجی
X11
adduser.conf
alternatives
apparmor.d
apt
--- تعداد آیتم‌های /etc:
140
--- ۳ خط وسط (خط‌های 5 تا 7):
198.51.100.23 - - [03/Oct/2026:12:00:05 +0000] "GET /index.html HTTP/1.1" 200 3611
198.51.100.23 - - [03/Oct/2026:12:00:06 +0000] "GET /api/users HTTP/1.1" 404 4617
198.51.100.7 - - [03/Oct/2026:12:00:07 +0000] "GET /static/app.js HTTP/1.1" 404 4871

در ls /etc | head -5، ls خروجی‌اش (صدها اسم) را به head می‌دهد و head فقط پنج تا را نگه می‌دارد. دستور سوم دو برنامه را برای «برش از وسط» ترکیب کرد. هر pipeline می‌تواند هر چند حلقه داشته باشد.

sort خط‌ها را مرتب می‌کند. پیش‌فرض: الفبایی (نه عددی!):

Terminal window
printf '10\n9\n100\n2\n' | sort
echo "--- sort -n (عددی):"
printf '10\n9\n100\n2\n' | sort -n
echo "--- sort -rn (عددی، معکوس):"
printf '10\n9\n100\n2\n' | sort -rn
echo "--- sort -u (مرتب و حذف تکراری):"
printf 'b\na\nb\nc\na\n' | sort -u
خروجی
10
100
2
9
--- sort -n (عددی):
2
9
10
100
--- sort -rn (عددی، معکوس):
100
10
9
2
--- sort -u (مرتب و حذف تکراری):
a
b
c

بدون -n، ۱۰۰ قبل از ۲ می‌آید (مقایسه‌ی کاراکتر به کاراکتر: 1 < 2). flag های مهم: -n عددی، -r معکوس، -u یکتا، -h اعداد خوانا مثل 2K 1M (برای خروجی du -h)، -k N مرتب‌سازی بر اساس ستون N، -t X جداکننده‌ی ستون:

Terminal window
echo "--- مرتب‌سازی /etc/passwd بر اساس UID، بزرگ‌ترین‌ها اول (ستون 3، جداکننده :):"
sort -t: -k3 -nr /etc/passwd | head -3 | cut -d: -f1,3
خروجی
--- مرتب‌سازی /etc/passwd بر اساس UID، بزرگ‌ترین‌ها اول (ستون 3، جداکننده :):
nobody:65534
ali:1001
ubuntu:1000

مثال ۳: شمارش تکراری‌ها، uniq -c

Section titled “مثال ۳: شمارش تکراری‌ها، uniq -c”

uniq خط‌های پشت‌سرهم یکسان را یکی می‌کند، پس ورودی باید مرتب باشد؛ -c تعداد را کنارش می‌نویسد:

Terminal window
echo "--- بدون sort (فقط تکرارهای پشت‌سرهم یکی می‌شوند):"
printf 'a\nb\na\na\nb\n' | uniq -c
echo "--- با sort اول:"
printf 'a\nb\na\na\nb\n' | sort | uniq -c
echo "--- فقط تکراری‌ها (-d):"
printf 'a\nb\na\nc\n' | sort | uniq -d
echo "--- فقط یکتاها (-u):"
printf 'a\nb\na\nc\n' | sort | uniq -u
خروجی
--- بدون sort (فقط تکرارهای پشت‌سرهم یکی می‌شوند):
1 a
1 b
2 a
1 b
--- با sort اول:
3 a
2 b
--- فقط تکراری‌ها (-d):
a
--- فقط یکتاها (-u):
b
c

الگوی ثابت: sort | uniq -c برای «هر مقدار چند بار آمده». این یکی از رایج‌ترین ترکیب‌های لینوکس است.

⚡ بررسی سریع

چرا قبل از uniq معمولاً sort می‌زنیم؟

cut بخشی از هر خط را برش می‌دهد: -d جداکننده، -f شماره‌ی ستون (fields)، -c شماره‌ی کاراکتر:

Terminal window
echo "--- ستون ۱ (IP) از ۳ خط اول:"
head -3 access.log | cut -d' ' -f1
echo "--- ستون‌های ۱ و ۹ (IP و وضعیت):"
head -3 access.log | cut -d' ' -f1,9
echo "--- ۱۰ کاراکتر اول:"
head -2 access.log | cut -c1-10
echo "--- نام کاربرها از /etc/passwd (جداکننده :):"
cut -d: -f1 /etc/passwd | head -4
خروجی
--- ستون ۱ (IP) از ۳ خط اول:
203.0.113.5
203.0.113.5
192.0.2.44
--- ستون‌های ۱ و ۹ (IP و وضعیت):
203.0.113.5 404
203.0.113.5 500
192.0.2.44 200
--- ۱۰ کاراکتر اول:
203.0.113.
203.0.113.
--- نام کاربرها از /etc/passwd (جداکننده :):
root
daemon
bin
sys

برای فایل‌هایی که ستون‌هایشان با فاصله‌ی متغیر جدا شده‌اند (مثل خروجی ps یا df) cut -d' ' درست کار نمی‌کند؛ آن‌جا از awk استفاده کن (درس بعد). دو حالت مفید دیگر: -f2- (از ستون ۲ تا آخر) و --complement.

مثال ۵: تبدیل کاراکتر، tr

Section titled “مثال ۵: تبدیل کاراکتر، tr”

tr (translate) کاراکتر به کاراکتر تبدیل یا حذف می‌کند. فقط از stdin می‌خواند (فایل نمی‌گیرد):

Terminal window
echo "hello world" | tr 'a-z' 'A-Z'
echo "--- حذف کاراکتر (-d):"
echo "شماره: 0912-345-6789" | tr -d '-'
echo "--- فشرده کردن تکرار (-s):"
echo "a b c" | tr -s ' '
echo "--- تبدیل فاصله به خط جدید:"
echo "one two three" | tr ' ' '\n'
echo "--- حذف کاراکتر \\r فایل ویندوزی:"
printf 'line1\r\nline2\r\n' | tr -d '\r' | od -c | head -2
خروجی
HELLO WORLD
--- حذف کاراکتر (-d):
شماره: 09123456789
--- فشرده کردن تکرار (-s):
a b c
--- تبدیل فاصله به خط جدید:
one
two
three
--- حذف کاراکتر \r فایل ویندوزی:
0000000 l i n e 1 \n l i n e 2 \n
0000014

کاربردهای رایج: حروف بزرگ/کوچک، حذف \r (فایل‌هایی که از ویندوز آمده‌اند)، فشرده کردن فاصله‌های اضافی، و شکستن کلمه‌ها به خط‌های جدا (برای شمارش کلمات).

با همین ابزارها یک گزارش بساز: هر کد وضعیت چند بار آمده؟

Terminal window
cut -d' ' -f9 access.log | sort | uniq -c | sort -rn
خروجی
1783 200
624 404
315 301
278 500

سه حلقه: cut ستون وضعیت را برید، sort | uniq -c شمرد، و sort -rn از بیشترین به کمترین چید. ۲۰۰ بیشترین است (موفق)، بعد ۴۰۴ و … . یک گزارش «چند درصد خطا داریم؟» فقط یک خط دیگر لازم دارد:

Terminal window
total=$(wc -l < access.log)
errors=$(cut -d' ' -f9 access.log | grep -c '^[45]')
echo "خطا: $errors از $total درخواست"
خروجی
خطا: 902 از 3000 درخواست

(grep را در درس بعد کامل یاد می‌گیری: grep -c '^[45]' یعنی «چند خط با ۴ یا ۵ شروع می‌شوند».)

مثال ۷: تمرین اصلی، ۱۰ آدرس IP پرتکرار

Section titled “مثال ۷: تمرین اصلی، ۱۰ آدرس IP پرتکرار”

همه‌ی چیزهایی که یاد گرفتی در یک pipeline:

Terminal window
cut -d' ' -f1 access.log | sort | uniq -c | sort -rn | head -10
خروجی
1055 203.0.113.5
667 198.51.100.7
405 192.0.2.44
230 192.0.2.8
222 203.0.113.77
212 203.0.113.9
209 198.51.100.23

خط به خط: cut ستون IP، sort تا یکسان‌ها کنار هم بیایند، uniq -c تعداد، sort -rn عددی و معکوس، head -10 ده‌تای اول. اگر فقط ۳ تای اول خواسته بودی head -3؛ اگر فقط IP بدون عدد: انتهای pipeline | awk '{print $2}' (یا cut -c9-). برای دیدن مرحله‌به‌مرحله، pipeline را قطعه‌قطعه اجرا کن و خروجی هر مرحله را ببین (روش عیب‌یابی pipeline).

مثال ۸: xargs، خروجی را به argument تبدیل کن

Section titled “مثال ۸: xargs، خروجی را به argument تبدیل کن”

بعضی دستورها (مثل rm، cp، mkdir) از stdin نمی‌خوانند؛ argument می‌خواهند. xargs ورودی‌اش را می‌خواند و آن را به argument های یک دستور تبدیل می‌کند:

Terminal window
mkdir -p xdemo && cd xdemo
echo "a b c" | xargs touch
ls
echo "--- هر ورودی در یک اجرا (-n 1):"
echo "x y z" | xargs -n 1 echo "پردازش:"
echo "--- جای‌گذاری با -I:"
printf 'one\ntwo\n' | xargs -I{} echo "فایل {} پردازش شد"
echo "--- ترکیب با find و wc:"
find . -type f | xargs wc -c | tail -1
خروجی
a
b
c
--- هر ورودی در یک اجرا (-n 1):
پردازش: x
پردازش: y
پردازش: z
--- جای‌گذاری با -I:
فایل one پردازش شد
فایل two پردازش شد
--- ترکیب با find و wc:
0 total

xargs touch سه فایل ساخت؛ -n 1 ورودی‌ها را یکی‌یکی می‌دهد؛ -I{} جای {} را با هر ورودی پر می‌کند. خطر اسم‌های دارای فاصله:

Terminal window
cd xdemo
touch "my file.txt"
echo "--- بدون -0 (اسم با فاصله می‌شکند):"
find . -name "my*" | xargs ls -l 2>&1 | head -2
echo "--- درست: -print0 با xargs -0 (جداکننده‌ی NUL):"
find . -name "my*" -print0 | xargs -0 ls -l | awk '{print $9, $10}'
خروجی
--- بدون -0 (اسم با فاصله می‌شکند):
ls: cannot access './my': No such file or directory
ls: cannot access 'file.txt': No such file or directory
--- درست: -print0 با xargs -0 (جداکننده‌ی NUL):
./my file.txt

xargs پیش‌فرض با فاصله و خط جدید خرد می‌کند، پس my file.txt دو argument می‌شود. راه امن: find -print0 | xargs -0 (جداکننده‌ی بایت NUL که در اسم فایل نمی‌آید). و xargs -P 4 چند اجرا را موازی انجام می‌دهد (مثلاً فشرده‌سازی ۴ فایل همزمان).

مثال ۹: وضعیت خروج یک pipeline

Section titled “مثال ۹: وضعیت خروج یک pipeline”

pipeline یک کد خروج دارد: کد آخرین دستور. ببین:

Terminal window
ls /no/such/dir 2>/dev/null | wc -l
echo "کد خروج pipeline: $?"
echo "--- کد خروج تک‌تک دستورها (PIPESTATUS):"
ls /no/such/dir 2>/dev/null | wc -l >/dev/null
echo "ls=${PIPESTATUS[0]} wc=${PIPESTATUS[1]}"
echo "--- با pipefail:"
set -o pipefail
ls /no/such/dir 2>/dev/null | wc -l >/dev/null
echo "کد خروج با pipefail: $?"
set +o pipefail
خروجی
0
کد خروج pipeline: 0
--- کد خروج تک‌تک دستورها (PIPESTATUS):
ls=2 wc=0
--- با pipefail:
کد خروج با pipefail: 2

ls خطا (۲) داد ولی چون wc موفق بود، کل pipeline 0 برگرداند: خطا گم شد! با set -o pipefail کد خروج اولین دستور ناموفق برمی‌گردد (برای اسکریپت‌های مهم همیشه بگذار)، و PIPESTATUS کد همه‌ی دستورها را دارد.

مثال ۱۰: دیدن وسط pipeline با tee

Section titled “مثال ۱۰: دیدن وسط pipeline با tee”
Terminal window
cut -d' ' -f1 access.log | sort | tee sorted-ips.txt | uniq -c | sort -rn | head -3
echo "--- فایل میانی ذخیره شد: $(wc -l < sorted-ips.txt) خط"
خروجی
1055 203.0.113.5
667 198.51.100.7
405 192.0.2.44
--- فایل میانی ذخیره شد: 3000 خط

tee (درس قبل) داخل pipeline یک «بازرس» می‌گذارد: داده را به فایل می‌ریزد و همزمان رد می‌کند. هنگام ساختن pipeline پیچیده، با tee خروجی مرحله‌ی میانی را ذخیره می‌کنی تا ببینی کجا خراب شده.

پشت پرده: pipe چطور کار می‌کند؟

Section titled “پشت پرده: pipe چطور کار می‌کند؟”

وقتی A | B را می‌نویسی، shell یک لوله‌ی هسته (pipe) می‌سازد (یک بافر کوچک در حافظه‌ی هسته، حدود ۶۴ کیلوبایت)، دو پروسه را همزمان اجرا می‌کند و stdout پروسه‌ی A را به سر نوشتن و stdin پروسه‌ی B را به سر خواندن لوله وصل می‌کند. اگر B کند باشد و بافر پر شود، A منتظر می‌ماند (back-pressure)؛ اگر لوله خالی باشد، B منتظر داده می‌ماند. به همین دلیل می‌توانی با pipe فایل ۱۰۰ گیگابایتی را پردازش کنی بدون اینکه حافظه پر شود: داده در جریان است، نه یکجا در حافظه.

نکته‌ی مهم: stderr وارد pipe نمی‌شود (فقط stdout). خطاها روی صفحه می‌مانند مگر 2>&1 یا |& بنویسی. و sort استثناست: چون باید همه‌ی ورودی را ببیند تا مرتب کند، تا پایان ورودی چیزی نمی‌دهد؛ در حالی که head پس از گرفتن ۱۰ خط خارج می‌شود و A با سیگنال SIGPIPE می‌میرد (نه اینکه تا آخر کار ادامه دهد). همین است که yes | head -1 تمام می‌شود.

دستور کار flag های مهم
sort مرتب‌سازی -n عددی، -r معکوس، -u یکتا، -k N ستون، -t X جداکننده، -h اعداد خوانا
uniq حذف تکراری‌های متوالی -c شمارش، -d فقط تکراری، -u فقط یکتا
cut برش ستون -d جداکننده، -f ستون، -c کاراکتر
tr تبدیل کاراکتر -d حذف، -s فشرده، 'a-z' 'A-Z'
wc شمارش -l خط، -w کلمه، -c بایت
head / tail ابتدا / انتها -n N
xargs تبدیل stdin به argument -n 1، -I{}، -0، -P N
tee شاخه‌ی میانی -a افزودن
الگوی رایج کار
... | sort | uniq -c | sort -rn | head «پرتکرارترین‌ها»
... | wc -l «چند تا؟»
find ... -print0 | xargs -0 cmd اجرای امن دستور روی فایل‌ها
set -o pipefail خطای وسط pipeline را گم نکن
Terminal window
printf 'a\nb\na\n' | uniq -c
خروجی
1 a
1 b
1 a

a دو بار جدا شمرده شد (۱، ۱، ۱) چون پشت‌سرهم نبودند. راه‌حل: sort | uniq -c.

Terminal window
printf '9\n10\n2\n' | sort | tr '\n' ' '; echo
printf '9\n10\n2\n' | sort -n | tr '\n' ' '; echo
خروجی
10 2 9
2 9 10

الفبایی: 10 2 9؛ عددی: 2 9 10. راه‌حل: -n برای عددها.

۳) فرض اینکه pipe خطا را هم می‌برد

Section titled “۳) فرض اینکه pipe خطا را هم می‌برد”
Terminal window
ls /no/such 2>&1 | wc -l
echo "---"
ls /no/such | wc -l
خروجی
1
---
ls: cannot access '/no/such': No such file or directory
0

بدون 2>&1، پیام خطا از pipe رد نشد و روی صفحه آمد (wc عدد ۰ را دید). راه‌حل: 2>&1 یا |&.

۴) xargs با اسم‌های دارای فاصله

Section titled “۴) xargs با اسم‌های دارای فاصله”

مثال ۸. راه‌حل: find ... -print0 | xargs -0 ....

۵) cut -d' ' روی ستون‌های با فاصله‌ی متغیر

Section titled “۵) cut -d' ' روی ستون‌های با فاصله‌ی متغیر”
Terminal window
printf 'a b\nc d\n' | cut -d' ' -f2

چون چند فاصله پشت هم هستند، cut ستون‌های خالی می‌بیند و خروجی عجیب می‌دهد. راه‌حل: اول tr -s ' ' برای فشرده کردن، یا awk '{print $2}'.

✎ تمرینآسان

از access.log تعداد کل خط‌ها و تعداد IP های یکتا را بشمار.

دیدن جواب
Terminal window
echo "خط‌ها: $(wc -l < access.log)"
echo "IP یکتا: $(cut -d' ' -f1 access.log | sort -u | wc -l)"
خروجی
خط‌ها: 3000
IP یکتا: 7
✎ تمرینمتوسط

تمرین اصلی: از یک فایل لاگ، ۱۰ آدرس IP پرتکرار را پیدا کن. فایل لاگ را بساز (مثل بالا) و با یک pipeline پنج‌حلقه‌ای IP های پرتکرار را با تعدادشان نشان بده، بعد نسخه‌ای که فقط اسم IP ها (بدون عدد) را چاپ کند.

دیدن جواب
Terminal window
awk 'BEGIN{for(i=1;i<=500;i++) print "10.0.0." (i*i%9+1) " GET /x"}' > log.txt
cut -d' ' -f1 log.txt | sort | uniq -c | sort -rn | head -10
echo "--- فقط IP ها:"
cut -d' ' -f1 log.txt | sort | uniq -c | sort -rn | head -10 | tr -s ' ' | cut -d' ' -f3
خروجی
166 10.0.0.1
112 10.0.0.8
111 10.0.0.5
111 10.0.0.2
--- فقط IP ها:
10.0.0.1
10.0.0.8
10.0.0.5
10.0.0.2
✎ تمرینسخت

یک گزارش سه‌بخشی از access.log بساز با یک pipeline برای هر بخش: (۱) ۳ مسیر (path) پرتکرار (ستون ۷)، (۲) تعداد درخواست‌های هر کد وضعیت، (۳) ۳ IP که بیشترین خطای ۴xx/۵xx را داشته‌اند (راهنما: grep یا awk برای فیلتر کد؛ می‌توانی از awk '$9 ~ /^[45]/ {print $1}' استفاده کنی).

دیدن جواب
Terminal window
awk 'BEGIN {
split("203.0.113.5 203.0.113.5 203.0.113.5 198.51.100.7 198.51.100.7 192.0.2.44 203.0.113.9 192.0.2.8", ip, " ")
split("200 200 200 404 404 500", st, " ")
split("/index.html /about /api/users /login", pa, " ")
for (i = 1; i <= 800; i++) printf "%s - - [x] \"GET %s HTTP/1.1\" %s 100\n", ip[(i*i+i)%8+1], pa[(i*5+int(i/9))%4+1], st[(i*3+int(i/7))%6+1]
}' > a.log
echo "== ۳ مسیر پرتکرار:"; cut -d' ' -f7 a.log | sort | uniq -c | sort -rn | head -3
echo "== کدهای وضعیت:"; cut -d' ' -f9 a.log | sort | uniq -c | sort -rn
echo "== IP های با بیشترین خطا:"; awk '$9 ~ /^[45]/ {print $1}' a.log | sort | uniq -c | sort -rn | head -3
خروجی
== ۳ مسیر پرتکرار:
800 HTTP/1.1"
== کدهای وضعیت:
800 100
== IP های با بیشترین خطا:
؟ آزمونک
  1. علامت | چه می‌کند؟

  2. چرا قبل از uniq -c معمولاً sort می‌زنیم؟

  3. sort -rn چه می‌کند؟

  4. cut -d: -f1 /etc/passwd چه می‌دهد؟

  5. xargs چه می‌کند؟

  6. pipeline کد خروج کدام دستور را برمی‌گرداند (پیش‌فرض)؟

  • pipe (|): stdout دستور چپ → stdin دستور راست؛ دستورها همزمان اجرا می‌شوند و داده در جریان است.
  • ابزارهای کوچک: sort (-n -r -u -k -t -h)، uniq -c، cut -d -f، tr، wc -l، head/tail، tee، xargs.
  • الگوی «پرتکرارترین‌ها»: cut ... | sort | uniq -c | sort -rn | head. uniq فقط تکرارهای متوالی را می‌گیرد، پس sort قبلش.
  • xargs خروجی را argument می‌کند؛ برای اسم‌های دارای فاصله find -print0 | xargs -0.
  • stderr وارد pipe نمی‌شود (مگر 2>&1 یا |&)؛ کد خروج pipeline کد آخرین دستور است؛ set -o pipefail و PIPESTATUS.
  • هنگام ساختن pipeline، مرحله‌به‌مرحله اجرا کن و با tee وسط را ببین.
برگه‌ی تقلب این درس
دستورکاری که می‌کند
cmd1 | cmd2خروجی cmd1 → ورودی cmd2
sort -n / sort -rnمرتب‌سازی عددی / عددی معکوس
sort -u / sort -k2یکتا / بر اساس ستون ۲
sort | uniq -cشمارش هر مقدار
cut -d" " -f1ستون اول با جداکننده‌ی فاصله
tr "a-z" "A-Z"تبدیل به حروف بزرگ
tr -d "\r"حذف \r
wc -lتعداد خط
cut -d" " -f1 f | sort | uniq -c | sort -rn | head۱۰ مقدار پرتکرار
find . -print0 | xargs -0 cmdاجرای امن روی فایل‌ها
cmd1 |& cmd2stdout و stderr هر دو به pipe
set -o pipefailخطای هر مرحله را برگردان