در دنیای رابط خط فرمان، برنامهها اغلب با سه جریان دادهی استاندارد سر و کار دارند:
stdin): جایی که برنامه ورودی خود را دریافت میکند (معمولاً از صفحهکلید).stdout): جایی که برنامه خروجی معمول خود را میفرستد (معمولاً به صفحهی ترمینال).stderr): جایی که برنامه پیامهای خطا را میفرستد (معمولاً به صفحهی ترمینال).به یاد بیاورید که اینها را در فصل خط لوله و فهرستهای دستور معرفی کردیم.
میتوان خط لوله را نوعی تغییر مسیر در نظر گرفت: خروجی استاندارد یک برنامه مستقیماً به ورودی استاندارد برنامهی دیگر فرستاده میشود. پیشتر به خط لوله پرداختهایم. این مفهوم به تغییر مسیر از فایلها و به فایلها میپردازد.
تغییر مسیر در شل سازوکاری قدرتمند است که به شما امکان میدهد مقصد این جریانها را تغییر دهید. بهجای اینکه برنامه از صفحهکلید بخواند یا روی صفحه بنویسد، میتوانید ورودی را از یک فایل تغییر مسیر دهید یا خروجی را به یک فایل بفرستید. این کار انعطاف و کنترل چشمگیری بر نحوهی تعامل برنامهها با داده فراهم میکند.
در ادامه رایجترین عملگرهای تغییر مسیر و کاری که انجام میدهند آمده است:
> (تغییر مسیر خروجی)هدف: تغییر مسیر خروجی استاندارد (stdout) یک دستور به یک فایل.
رفتار:
مثال:
# Sends the output of 'ls -l' to 'file_listing.txt'
ls -l > file_listing.txt
تغییر مسیر پیش از اجرای دستور انجام میشود. یعنی نمیتوانید به همان فایلی تغییر مسیر دهید که باید از آن بخوانید.
date > date.txt # populate the file with the current date
cat date.txt > date.txt # 'date.txt' is now empty!
در دستور دوم مثال بالا،
>> (تغییر مسیر خروجی با افزودن)هدف: افزودن خروجی استاندارد (stdout) یک دستور به یک فایل.
رفتار:
مثال:
# Adds "Another line" to the end of the file
echo "Another line" >> file_listing.txt
< (تغییر مسیر ورودی)هدف: تغییر مسیر ورودی استاندارد (stdin) یک دستور از یک فایل.
رفتار: دستور ورودی خود را بهجای صفحهکلید از فایل مشخصشده میخواند.
مثال:
# 'tr' reads from 'lowercase.txt' and
# output is redirected to 'uppercase.txt'
tr 'a-z' 'A-Z' < lowercase.txt > uppercase.txt
2> (تغییر مسیر خطا):stderr) یک دستور به یک فایل.# Error message from 'rm' is sent to 'error_log.txt'
rm non_existent_file 2> error_log.txt
میتوانید خطای استاندارد را با 2>> به یک فایل بیفزایید.
تغییر مسیرهایی هم وجود دارند که میتوانند stdin و stderr را با هم ادغام کنند.
برای جزئیات به راهنما مراجعه کنید.
/dev/null/dev/null یک فایل ویژه است که
گاهی آن را «سبد بیت» مینامند. برای جلوگیری از نمایش خروجی یا خطاها مفید است.
some_command > /dev/null # Discards stdout
some_command 2> /dev/null # Discards stderr
# Using /dev/null as input will prevent the command
# from reading data from the keyboard
some_command < /dev/null
میتوان چندین تغییر مسیر را همزمان نوشت.
some_command < input.txt > output.txt 2> error.txt
میتوان یک تغییر مسیر را کپی کرد.
# send stderr to the same destination as stdout
some_command > output.txt 2>&1
وقتی 2>&1 را میبینید، آن را اینطور بخوانید: «خطای استاندارد را به هر جایی که خروجی استاندارد همین حالا به آن اشاره میکند تغییر مسیر بده».
Bash دستورهای تغییر مسیر را دقیقاً از چپ به راست پردازش میکند، یعنی میتوانید این کار را بکنید:
# redirect stdout to 'output1.txt'
# redirect stderr to the same place
# then change stdout to 'output2.txt'
some_command > output1.txt 2>&1 > output2.txt
در بستر برنامهنویسی شل و سیستمعاملهایی مانند Linux/Unix، توصیفگر فایل (FD) یک عدد صحیح نامنفی است که بهعنوان شناسه یا دستگیرهای برای یک فایل باز یا منبع ورودی/خروجی (I/O) عمل میکند. آن را مانند یک برچسب یا شمارهی مرجع در نظر بگیرید که سیستمعامل برای پیگیری فایلهای باز و جریانهای داده از آن استفاده میکند.
شمارههایی که در سمت چپ تغییر مسیرها میبینید، توصیفگرهای فایل هستند.
به جریانهای ورودی/خروجی استاندارد، سه توصیفگر فایل نخست اختصاص داده میشود:
توصیفگرهای فایل تازه را میتوان با دستور exec و عملگرهای تغییر مسیر تعیین یا ایجاد کرد.
# create FD 3 as a copy of stdout
exec 3>&1
# send stdout to a log file
exec > log.txt
# then redirect both stdout and file descriptor 3
echo "some debug message" >&3 # displayed in the terminal
some_command 2>&1 # stdout and stderr send to 'log.txt'
این تکنیک نسبتاً پیچیده به نظر میرسد، اما میتواند در موقعیتهایی بسیار مفید باشد که اسکریپت شما توسط بستهی نرمافزاری دیگری اجرا میشود و خروجی استاندارد بهطور خودکار توسط آن نرمافزار گرفته میشود.
دستور bats که برای اجرای testهای واحد این مسیر یادگیری به کار میرود، اینگونه کار میکند: bats خروجی و خطای استاندارد یک test را میگیرد، اما پیامهای debug که به FD ۳ فرستاده میشوند روی ترمینال نمایش داده میشوند.
چرا تغییر مسیر مفید است؟
تغییر مسیرهای شل کنترل دقیقی بر نحوهی تعامل برنامهها با داده به شما میدهد و به شما امکان میدهد گردشکارهای پیچیده بسازید و اطلاعات را بهطور مؤثر مدیریت کنید.