آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

پرسش و پاسخ شماره ۶۰

پرسش و پاسخ شماره ۶۰

من سعی می‌کنم اسکریپتی بنویسم که دایرکتوری جاری را تغییر دهد( یا یک متغیر را تنظیم کند)، اما بعد از به پایان رسیدن اسکریپت، در همان جایی هستم که از آنجا شروع کرده بودم(یا متغیر من نیست)!

این را ملاحظه نمایید:

   #!/bin/sh
   cd /tmp

اگر شخصی این اسکریپت را اجرا نماید، چه اتفاقی روی می‌دهد؟ Bash منشعب می‌شود که به یک والد(پوسته محاوره‌ای که فرمان در آن تایپ شده) و یک فرزند(پوسته جدیدی که اسکریپت را می‌خواند و اجرا می‌کند) منجر می‌گردد. فرزند اجرا می‌شود، در حالیکه پدر برای خاتمه یافتن آن منتظر می‌ماند. فرزند اسکریپت را می‌خواند و اجرا می‌کند، دایرکتوری جاری آن به ‎ /tmp‎ تغییر می‌کند، و سپس خارج می‌شود. والد که در انتظار فرزند است،کد وضعیت فرزند را تحصیل می‌کند(احتمالاً صفر در اثر موفقیت)، و سپس با دستور بعدی ادامه می‌دهد. هیچ جایی در این پردازش دایرکتوری کاری پدر تغییر نکرده است -- فقط دایرکتوری فرزند تغییر کرد.

پردازش فرزند هرگز بر هیج بخشی از محیط والد، که شامل متغیرهایش، دایرکتوری کاری‌اش، فایلهای بازش، محدودیت منابعش، و غیره می‌شود، اثر نمی‌گذارد.

بنابراین، چطور فردی تقلا می‌کند دایرکتوری جاریوالد را تغییر بدهد؟ هنوز می‌توانید فرمان cd را در یک فایل خارجی داشته باشید، اما نمی‌توانید به عنوان اسکریپت آنرا اجراکنید. اجرای آن باعث انشعابی که قبلاً تشریح شد، می‌گردد. به جای آن شما باید با دستور .(یا دستور source مترادف آن، فقط در Bash) آن را منبع کنید. منبع کردن اساساً به معنی آنست که شما فرمانها را در یک فایل با استفاده از پوسته جاری اجرا می‌کنید، نه در یک پوسته منشعب(شل فرزند):

   echo 'cd /tmp' > "$HOME/mycd"      #‎ ایجاد می‌کند‎ 'cd /tmp' فایلی محتوی فرمان 
   . $HOME/mycd          # در شل جاری 'cd /tmp' آن فایل منبع می‌شود، اجرای فرمان
   pwd                   #  هستیم /tmpاکنون ما در شاخه 

همین مورد در تنظیم متغیرها اِعمال می‌گردد. . ("dot in") فایلی که شامل دستورات است، سعی نمی‌کند آن فایل را اجرا کند.

اگر دستوری که اجرا می‌کنید یک تابع است، نه یک اسکریپت، در پوسته جاری اجرا خواهد شد. بنابراین، ممکن است برای انجام آنچه در مثال فوق سعی کردیم با فایل خارجی انجام بدهیم، بدون احتیاج به هر گونه "dot in" یا "source" یک تابع تعریف شود. تعریف تابع زیر و سپس فراخوانی ساده آن با تایپ mycd:

   mycd() { cd /tmp; }

اگر می‌خواهید به طور خودکار در پوسته جدیدی که باز می‌کنید تابع در دسترس باشد، آن را در ‎ ~/.bashrc یا مشابه آن قرار بدهید.

بعضی اشخاص ترجیح می‌دهند از مستعارها در عوض توابع استفاده کنند. توابع بیشتر قدرتمند ، عمومی‌تر، قابل انعطاف‌تر، و.... می‌باشند، فقط به نظر می‌رسد بعضی افراد آنها را دوست ندارند.

   alias mycd='cd /tmp'  # .معادل تابع نشان داده شده در بالا

   alias cdlstmp='cd /tmp && ls tmp*'
   # شروع می‌شوند "tmp" می‌برد و نشان می‌دهد آنجا کدام فایلها با /tmp شما را به  

   cdls() { cd "$1" && ls; }
   # توسط مستعارها نمی‌تواند انجام شود‎
   #  cdls directory نحوه استفاده

پرسش و پاسخ 60 (آخرین ویرایش ‎ 2012-01-27 22:50:33 ‎ توسط 125)