همیشه سه فایل قراردادی[1] باز وجود دارد، stdin (صفحه کلید)، stdout (صفحه نمایش)، و stderr (پیغام خطاهای خروجی روی نمایشگر). اینها، و هر فایل باز دیگر، میتوانند تغییر مسیر داده شوند. تغییر مسیر فقط به معنی گرفتن خروجی از یک فایل، فرمان، برنامه، اسکریپت، یا حتی قطعه کدی در داخل یک اسکریپت (مثال 3-1 و مثال 3-2 را ببینید) و فرستادن آن به ورودی یک فایل، فرمان، برنامه، یا اسکریپت دیگر است.
هر فایل باز، یک توصیفگر فایل تخصیص یافته را کسب میکند. [2] توصیفگرهای فایل برای stdin، stdout، و stderr به ترتیب 0، 1، و 2 هستند. برای فایلهای باز اضافی، توصیفگرهای 3 تا 9 وجود دارند. گاهی اوقات تخصیص یکی از این توصیفگرهای فایل اضافی به stdin، stdout، یا stderr به عنوان یک نسخه دوم موقت، مفید است. [3] این تخصیص، بازگشت به حالت عادی پس از تغییر مسیر پیچیده و تجدید سازمان را تسهیل مینماید (مثال 20-1 را ببینید).
فرمانهای تغییر مسیر یک سطری (فقط روی سطری که در آن هستند اثر میکنند):
--------------------------------------------------------------------تغییر مسیر stdout به صورت یک سطر در هر نوبت.
LOGFILE=script.log echo "This statement is sent to the log file, \"$LOGFILE\"." 1>$LOGFILE echo "This statement is appended to \"$LOGFILE\"." 1>>$LOGFILE echo "This statement is also appended to \"$LOGFILE\"." 1>>$LOGFILE echo "This statement is echoed to stdout, and will not appear in \"$LOGFILE\"." #این فرمانهای تغییر مسیر به طور خودکار پس از هر سطر reset میشوند.
تغییر مسیر stderr به صورت یک سطر در هر نوبت.
ERRORFILE=script.errors bad_command1 2>$ERRORFILE #پیغام خطا به $ERRORFILE فرستاده میشود. bad_command2 2>>$ERRORFILE #پیغام خطا به $ERRORFILE پیوست میگردد. bad_command3 #پیغام خطا در stderr منعکس میشود و #+در $ERRORFILE ظاهر نمیشود. #این فرمانهای تغییر مسیر به طور خودکار پس از هر سطر reset میشوند.
یک کاربرد آن، نوشتن در یک محل تعیین شده در یک فایل است.
echo 1234567890 > File #نوشتن رشته در «File». exec 3<> File #بازکردن «File» و تخصیص fd 3 به آن. read -n 4 <&3 #خواندن فقط 4 کاراکتر. echo -n . >&3 #نوشتن یک نقطه اعشار در آنجا. exec 3>&- #بستن fd 3. cat File # #چه جالب!!! دستیابی غیر ترتیبی.
چندین نمونه از تغییر مسیر ورودی و خروجی و-یا لوله میتواند در یک سطر فرمان واحد ترکیب گردد.
command < input-file > output-file #مثال 16-31 و مثال A-14 را ببینید.یا معادل: < input-file command > output-file #هر چند که این غیر استاندارد است. command1 | command2 | command3 > output-file
ممکن است چند جریان خروجی به یک فایل تغییر مسیر داده شوند.
اما، توجه نمایید که مورد زیر همان نتیجه را ارایه نمیکند.
بستن توصیفگرهای فایل
بستن توصیفگر فایل ورودی n.
بستن stdin.
بستن توصیفگر فایل خروجی n.
بستن stdout.
پردازشهای فرزند، توصیفگرهای فایل باز را به ارث میبرند. بدین علت لولهها کار میکند. برای پیشگیری از به ارث رسیدن یک توصیفگر فایل، آن توصیفگر را ببندید.
#تغییر مسیر دادن stderr تنها، به یک لوله. exec 3>&1 #ذخیره مقدار فعلی stdout ls -l 2>&1 >&3 3>&- | grep bad #بستن fd 3 برای grep (امابرای ls خیر). # exec 3>&- #اکنون بستن آن برای باقیمانده اسکریپت. #با تشکر از S.C.
برای معرفی مفصلتر تغییر مسیر ورودی-خروجی پیوست F را ببینید.
[1] | مطابق قرارداد در یونیکس و لینوکس، با جریانهای داده و دستگاههای جانبی (فایلهای دستگاه) به عنوان فایل و به روشی متشابه با فایلهای معمولی، رفتار میشود. |
[2] | یک توصیفگر فایل فقط یک عدد است که سیستمعامل به یک فایل باز برای دیدهبانی آن تخصیص میدهد. آن را همچون نوع ساده شده اشارهگر فایل در نظر بگیرید. مشابه file handle در C است. |
[3] | به کار بردن توصیفگر فایل 5 میتواند باعث مشکل بشود. وقتی Bash یک پردازش فرزند تولید میکند، به عنوان مثال با exec، فرزند fd 5 را به ارث میبرد (ایمیل آرشیو شده Chet Ramey، SUBJECT: RE: File descriptor 5 is held open را ببینید). بهتر است این fd خاص را رها کنید. |