آموزش‌های خط فرمانی

این وبلاگ تلاش می‌کند گامی در حد بضاعت در جهت آموزش خط فرمان و اسکریپت‌نویسی پوسته گنو-لینوکس بردارد.

آموزش‌های خط فرمانی

این وبلاگ تلاش می‌کند گامی در حد بضاعت در جهت آموزش خط فرمان و اسکریپت‌نویسی پوسته گنو-لینوکس بردارد.

پرسش و پاسخ شماره ۲



چگونه می‌توانم مقدار برگشتی یا خروجی دستوری را در یک متغیر ذخیره نمایم؟

خوب، بستگی دارد به اینکه آیا می‌خواهید خروجی فرمان را ذخیره کنید(هر یک از stdout یا stdout + stderr) یا وضعیت خروج آن(0 تا 255، به طور نوعی در ازای 0 به معنی موفقیت).

اگر می‌خواهید خروجی را تصرف نمایید، از جایگزینی فرمان استفاده کنید:

    output=$(command)      # stdout only; stderr remains uncaptured
    output=$(command 2>&1) # both stdout and stderr will be captured

اگر وضعیت خروج را می‌خواهید، از پارامتر ویژه ‎$?‎ بعد از اجرای فرمان استفاده نمایید:

    command
    status=$?

اگر هر دو را می‌خواهید:

    output=$(command)
    status=$?

تخصیص به output تأثیری بر وضعیت خروج command، که بازهم در متغیر ‎ $?‎ است، ندارد.

اگر در واقع نمی‌خواهید وضعیت خروج را ذخیره کنید، اما می‌خواهید بر مبنای موفقیت یا شکست، عملی انجام شود، فقط از if استفاده نمایید:

    if command; then
        echo "it succeeded"
    else
        echo "it failed"
    fi

یا اگر می‌خواهید خروجی استاندارد را ذخیره کنید و بدون ذخیره نمودن یا بررسی ‎$?‎ به طور صریح، عملی نیز نسبت به موفقیت یا شکست، انجام شود، از این:

    if output=$(command); then
        echo "it succeeded"
    ...

اگر وضعیت خروج یک فرمان از خط‌لوله را می‌خواهید، چطور؟ اگر وضعیت خروج آخرین فرمان را می‌خواهید، مشکلی نیست-- در متغیر ‎ $?‎ است، درست مثل قبل. اگر وضعیت خروج بعضی از فرمانهای دیگر را می‌خواهید، از آرایه PIPESTATUS (منحصر به BASH )استفاده کنید. بر فرض که شما وضعیت خروج فرمان grep در کد زیر را می‌خواهید:

    grep foo somelogfile | head -5
    status=${PIPESTATUS[0]}

Bash نگارش 3.0 گزینه pipefail را نیز اضافه نموده ، که اگر شما واقعاً می‌خواهید در نتیجه شکست grep عملی انجام شود، می‌تواند استفاده شود:

    set -o pipefail
    if ! grep foo somelogfile | head -5; then
        echo "uh oh"
    fi

حالا، چند مورد زیرکانه. بیایید فرض کنیم فقط خروجی استاندارد خطا را می‌خواهید، اما خروجی استاندارد را نمی‌خواهید. خوب، پس اول باید تصمیم بگیرید که می‌خواهید خروجی استاندارد به کجا برود:

 output=$(command 2>&1 >/dev/null) #.خروجی خطا ذخیره و خروجی صرفنظر می‌شود
 output=$(command 2>&1 >/dev/tty)  #. ذخیره و خروجی به ترمینال ارسال می‌شود stderr
 output=$(command 3>&2 2>&1 1>&3-) #.اسکریپت می‌رودstderr ذخیره و خروجی به stderr

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

 exec 3>&1                    # به آن اشاره می‌کند stdout(1) ذخیره مکانی که 
 output=$(command 2>&1 1>&3)  # ذخیره می‌شود stderr .اجرای فرمان 
 exec 3>&-                    #  شماره 3  FD بستن‎
 # :را با اجازه عبور به خروجی از میان آن، ذخیره می‌کند stderr یا این جایگزین که 
 { output=$(command 2>&1 1>&3-) ;} 3>&1

توجه نمایید، که در آخرین مثال فوق ‎ 1>&3-‎ توصیف‌گر فایل 3 را دو نسخه‌ای می‌کند و یک نسخه از آن را در FD شماره 1 ذخیره می‌نماید، و FD شماره 3 را می‌بندد. که به این شکل نیز می‌تواند نوشته شود ‎1>&3 3>&-‎.

آنچه که نمی‌توانید انجام بدهید، ذخیره خروجی استاندارد در یک متغیر و stderr در دیگری، با استفاده ازتغییر مسیر FD به تنهایی است. شما باید از یک فایل موقت(یا لوله با نام) برای رسیدن به آن یک، استفاده نمایید.

خوب، می‌توانید یک شکاف ناخوش‌آیند(مترجم: منظور جمله« ... this line is » می‌باشد) به کار ببرید:

   result=$( { stdout=$(cmd) ; } 2>&1; echo "this line is the separator"; echo "$stdout")
   var_out=${result#*this line is the separator$'\n'}
   var_err=${result%$'\n'this line is the separator*}

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

و اگر شما کُد وضعیت cmd خود را خواسته باشید(این اصلاح برای حالتی است که اگر خروجی cmd تهی باشد)

   cmd() { curl -s -v http://www.google.fr; }

   result=$( { stdout=$(cmd); returncode=$?; } 2>&1; echo -n "this is the separator"; echo "$stdout"; exit $returncode)
   returncode=$?

   var_out=${result#*this is the separator}
   var_err=${result%this is the separator*}

یادداشت: پرسش اصلی، «چگونه می‌توانم مقدار برگشتی دستوری را در متغیری ذخیره کنم؟» بود. این کلمه به کلمه یک پرسش واقعی، پرسیده شده در ‎ #bash‎ است، مبهم و کلی.


CategoryShell

پرسش و پاسخ 2 (آخرین ویرایش‎ 2012-12-04 09:50:10 ‎ توسط geirha)


پرسش و پاسخ شماره ۱



1. چطور می‌توانم یک فایل(جریان داده، متغیر) را سطر به سطر بخوانم(و یا فیلد به فیلد)؟

استفاده از "for" را امتحان نکنید . از یک حلقه while و فرمان read استفاده کنید:

    while read -r line
    do
        echo "$line"
    done < "$file"
پاسخ مشروح را در اینجا ملاحظه نمایید: ‎[BashFAQ/001]‎

بار دیگر وفای به عهد

ترجمه راهنمای BashGuide به پایان رسید، و در ضمن به صورت یک فایل pdf نیز فراهم گردیده، که قابل دریافت می‌باشد، اما همانگونه که قبلاً اشاره شد، این راهنما بخشی از یک Wiki است، که گسترده‌تر از این راهنما می‌باشد.

در شروع ترجمه این راهنما به صورت یادداشت‌های ادامه‌دار، نوشتم که پس از تکمیل ترجمه راهنما احتمالاً به ترجمه سایر بخشها خواهم پرداخت. اکنون زمان اجرای آن تعهد ضمنی فرا رسیده است، و من برای ادامه، بخش «پرسش و پاسخ‌های رایج Bash» از این Wiki را انتخاب نموده‌ام که به همان روال سابق به صورت یاداشت‌های متوالی در اینجا قرار خواهم داد.

سعی خواهد شد در هر یادداشت یک پرسش و پاسخ به طور کامل ارایه شود، مگر در مواردی که پاسخ خیلی طولانی و خارج از حوصله یک یاداشت باشد، که البته مواردی اینچنین نیز وجود دارد.

اکنون در ادامه، فهرست پرسش و پاسخ‌ها را ملاحظه می‌نمایید.

من ترجیح می‌دهم پرسش و پاسخ‌ها را به ترتیب ارائه نمایم زیرا نگاه من به این ترجمه‌ها بیشتر یک نگاه بلندمدت است، نه رفع نیاز فوری، بنابراین چنین عمل خواهم نمود، مگر آنکه درخواست‌های چندگانه‌ای برای خارج از نوبت قرار دادن برخی از پرسش‌ها وجود داشته باشد.

ادامه مطلب ...

اشکالزدایی

ادامه یادداشت قبل


6. اشکالزدایی

خیلی وقتها، خودتان را مستأصل می‌بینید که چرا، اسکریپت شما آنگونه عمل نمی‌کند، که شما می‌خواهید. حل این مسئله همواره، موضوع درک عمومی و شیوه‌های اشکال‌یابی است.

تشخیص مشکل

بدون آنکه دقیقاً بدانید مشکل چیست، به احتمال بسیار زیاد، خیلی زود نمی‌توانید چاره‌سازی نمایید. بنابراین مطمئن شوید، که به طور دقیق می‌دانید چه چیز اشتباه است. علائم و پیغام‌های خطا را بررسی و ارزیابی کنید.

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


حداقل‌سازی کد اصلی

اگر اشکال‌یابی اسکریپت را شروع می‌کنید، به خودتان الهام خدایی اهدا نکنید، مورد دیگری که باید انجام دهید، کوشش جهت حداقل‌سازی کد اصلی برای مجزا نمودن مسئله می‌باشد.

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

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

به مجرد اینکه، موردی که مشکل ایجاد نموده را حذف کردید، دست بکشید(یا موردی که اضافه نمودنش دوباره آن مشکل را ظاهر می‌کند)، شما کشف کرده‌اید که مشکل در کجا قرار دارد. حتی اگر به طور دقیق به آن نرسیده‌اید، حداقل دیگر به یک اسکریپت حجیم خیره نمی‌شوید، بلکه امیدوارانه، با کوتوله‌ای نه بیش از 3 تا 7 سطر، مواجه هستید.

برای مثال، اگر اسکریپتی دارید که باز کردن فایلهای تصویری موجود در شاخه image را برحسب تاریخ برای شما انجام می‌دهد، و بنا به دلایلی، تکرار روی فایلهای دایرکتوری را نمی‌توانید به طور صحیح پیش ببرید، کافی است اسکریپت را تا اندازه این قطعه کُد کاهش بدهید:

    for image in $(ls -R "$imgFolder"); do
        echo "$image"
    done

اسکریپت واقعی شما به مراتب پیچیده‌تر از این خواهد بود، و درون حلقه for آن نیز طولانی‌تر خواهد بود. اما اصل مشکل این کُد است. وقتی مشکل را به این اندازه محدود کنید، ممکن است دیدن آنکه با چه مشکلی مواجه هستید، آسانتر باشد. دستور echo اجزاء نام فایلها را بیرون می‌دهد، به نظر می‌رسد تمام فضاهای سفید با کاراکتر سطرجدید تعویض گردیده‌اند. باید اینطور باشد، زیرا echo برای هرقسمت از نام فایل که منتهی به فضای سفید است، اجرا می‌شود، نه برای هر نام تصویر(در نتیجه، به نظر می‌رسد، خروجی نام فایلهایی که دارای فضای سفید می‌باشند، تفکیک شده‌اند). با این کُد کاهش یافته، دیدن آنکه مسبب واقعی، جمله for است که خروجی ls را به کلمات تفکیک نموده، آسانتر است. هرگز ls را در اسکریپتها به کار نبرید، مگر آنکه بخواهید خروجی آنرا به کاربر نمایش بدهید.

ما نمی‌توانیم glob بازگشتی به کار ببریم(مگر در bash نگارش 4)، بنابراین باید دستور find را برای به دست آوردن نام فایلها به کار بگیریم. یک راه اصلاح آن، چنین خواهد بود:

    find "$imgFolder" -print0 | while IFS= read -r -d '' image; do
        echo "$image"
    done

اکنون که مشکل را در این مثال کوچک برطرف نموده‌اید، برگشتن و ترکیب کردن آن با اسکریپ اصلی آسان است.


فعال نمودن وضعیت اشکال‌یابی BASH

اگر بازهم خطای روش‌هایتان را نمی‌بینید، شاید وضعیت اشکال‌یابی BASH برای دیدن مشکل در میان کُد به شما کمک نماید.

موقعی که BASH با گزینه ‎-x‎ اجرا می‌شود، این وضعیت فعال می‌گردد، هر دستوری را قبل از اجرا در خروجی چاپ می‌کند. همینطورهم ، بعد از هر بسط و گسترشی که انجام شده است. در نتیجه، به طور دقیق می‌توانید ببینید با اجرای هر سطر کُد، چه اتفاقی رخ می‌دهد. به نقل‌قول‌های استفاده شده خیلی دقیق توجه نمایید. BASH نقل‌قولها را برای نشان دادن آنکه دقیقاً کدام رشته به عنوان یک شناسه منفرد عبور داده شده، به کار می‌برد.

سه روش برای فعال کردن این وضعیت موجود است.

  • اجرای اسکریپت به صورت ‎ bash -x‎:

          $ bash -x ./mybrokenscript
  • ویرایش سرآیند اسکریپت:
          #!/bin/bash -x
          [.. script ..]
    
  • یا:
          #!/usr/bin/env bash
          set -x
    
  • یا اضافه نمودن ‎set -x‎ در جایی از کُد برای فعال کردن این حالت، منحصراً برای قطعه معینی از کُد:

          [..کدهای بی ارتباط..]
          set -x
          [..قطعه کد مرتبط..]
          set +x
          [..کدهای بی ارتباط..]
  • اگر ‎set -x‎ شما مقدار زیادی خروجی دارد، ویژگی دلپذیر bash نگارش 4.1 و بالاتر، متغیر BASH_XTRACEFD است. این متغیر امکان تعیین یک توصیف‌گر فایل برای هدایت خروجی اشکال‌های ‎set -x‎ به آن را فراهم می‌کند. در نسخه‌های قدیمی‌تر bash، همواره این خروجی به stderr می‌رفت، و اگر جدا کردن آن از خروجی معمولی ناممکن نبود، ولی دشوار بود. این هم یک روش دلپسند برای کاربرد آن:

        # ‎ را در یک فایل کپی می‌کند set -x ‎بخش 
        # ‎با یک نام فایل به عنوان 1$ آنرا فعال می‌کند‎
        # اگر پارامتری وجود نداشته باشد آن را غیر فعال می‌کند
        # ‎شماره  4 نباید در جای دیگری از اسکریپت استفاده شده باشد fd ‎
        setx_output()
        {
            if [[ $1 ]]; then 
               exec 4>>"$1"
               BASH_XTRACEFD=4
               set -x
            else
               set +x
               exec 4>&-
            fi
        }

اگر اسکریپت‌های پیچیده و آشفته‌ای دارید، شاید تغییر محتوی متغیر PS4 قبل از برقراری اشکال‌یابی با ‎ -x را سودمند بیابید:

      export PS4='+$BASH_SOURCE:$LINENO:$FUNCNAME: '


Step your code

اگر خروجی اشکال‌یابی از نظر شما خیلی سریع عبور می‌کند، می‌توانید کُد-مرحله‌ای را فعال کنید. کُد زیر از DEBUG دستور trap برای اطلاع به کاربر در باره دستوری که اجرا خواهد شد و انتظار برای تایید پیشرفت، استفاده می‌کند. این کُد را در محلی از اسکریپت خود که می‌خواهید مرحله‌ای بشود، قرار دهید:

    trap '(read -p "[$BASH_SOURCE:$LINENO] $BASH_COMMAND?")' DEBUG


اشکالزدای BASH

پروژه اشکالزدای Bash یک اشکال‌یاب gdb-مانند، در آدرس /http://bashdb.sourceforge.net است.

اشکال‌یاب فوق به شما کمک می‌کند در سرتاسر اسکریپت حرکت نموده و اشکالهای آن را پیگردی و پیدا کنید.


بازخوانی مستندات

اگر هنوز به نظر می‌رسد اسکریپت برایتان قابل قبول نیست، شاید ادراک شما از روش انجام کارها اشتباه است. به مستندات(یا این راهنما) رجوع کنید، برای ارزیابی آن که آیا فرمانها درست همانگونه که شما در مورد آنها می‌اندیشید کارمی‌کنند، یا دستور زبان کاربرد آنها همانطور است که شما فکر می‌کنید. بسیاری اوقات، اشخاص در باره چگونگی کارکرد for ، عملکرد تفکیک کلمه، یا اینکه چگونه باید از نقل‌قولها استفاده کنند، درک ناقصی دارند.

نکته‌ها را حفظ کنید و تکرارهای راهنمایی این آموزش را خوب به خاطر بسپارید. اینها غالباً برای پرهیز از مشکلات در اسکریپت‌ها به شما کمک می‌کنند.

من این مطلب را در بخش اسکریپهای این راهنما نیز اشاره کرده‌ام، اما تکرار آن در اینجا هم با ارزش است. اول از همه، اطمینان حاصل کنید که سرآیند اسکریپت شما به راستی ‎#! /bin/bash‎ است. اگر از قلم افتاده یا اگر موردی مانند این ‎#! /bin/sh‎ است، پس شما سزاوار مشکلاتی که دارید، هستید. چون به آن معنی است که احتمالاً حتی از BASH برای اجرای اسکریپت خود استفاده نمی‌کنید. به طور وضوح علت مشکل همانست. همچنین، اطمینان حاصل کنید که کاراکترهای رفتن سر سطر(CF) در انتهای سطرها ندارید. این به سبب اسکریپتهایی است که در ویندوز نوشته شده‌اند. می‌توانید به آسانی به طور مساعدی اینها را به این صورت پاک کنید:

  •     $ tr -d '\r' < myscript > tmp && mv tmp myscript


پرسش و پاسخها و Pitfallها را بخوانید

صفحه‌های پرسش و پاسخهای رایج و دام‌های Bash تصورات غلط معمول و مشکلاتی که دیگران در اسکریپت‌های BASH با آنها روبرو شده‌اند را شرح می‌دهند. احتمال بسیار دارد، مشکل شما به شکلی در آنجا تشریح شده باشد.

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


از ما در IRC بپرسید

در 24 ساعت هفت روز هفته، اکثراً افرادی در کانال ‎#bash‎ حضور دارند. این کانال در شبکه freenode IRC مستقر است. برای رسیدن به ما، لازم است یک سرویس‌گیرنده IRC داشته باشید. از طریق آن به ‎irc.freenode.net‎ و ‎/join #bash ارتباط برقرار نمایید.

مطمئن شوید که می‌دانید مشکل واقعی چیست و آنرا به صورت مرحله‌ای روی کاغذ بیاورید، به طوری که خوب بتوانید آنرا شرح بدهید. ما دوست نداریم در مورد مسائل حدس بزنیم. با توضیح آنکه اسکریپت شما چه کاری باید انجام بدهد شروع کنید.

نکته دیگر، لطفاً قبل از ورود به ‎#bash‎ صفحه : XyProblem را ملاحظه نمایید.


پایان راهنمای BashGuide

هرگز این کارها را نکنید

ادامه یادداشت قبل


5. هرگز این موارد را انجام ندهید

پوسته Bash امکان انجام کارهای بسیاری برای شما فراهم می‌کند، ارائه قابلیت انعطاف‌پذیری قابل ملاحظه به شما. متأسفانه، خیلی کم شما را از سوءمصرف و دیگر رفتارهای نامطلوب، بر حذر می‌دارد. امید می‌رود، اشخاص خودشان دریابند که از برخی مسائل معین باید به هر قیمتی پرهیز نمایند.

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

برای پاکیزگی اسکریپت‌هایتان، و به خاطر تمام افراد بشر، هرگز هیچ موردی از سطور زیر را انجام ندهید:

  • ls -l | awk '{ print $8 }'

    • هرگز تجزیه خروجی فرمان ls را انجام ندهید! خروجی فرمان ls به چند دلیل نمی‌تواند قابل اعتماد باشد.

      1. اول، اگر نام فایلها شامل کاراکترهای پشتیبانی نشده زبان محلی شما باشد، ls نامها را خُرد خواهد نمود. در نتیجه، خروجی حاصل از تجزیه نام فایلها توسط ls، هرگز تضمین نمی‌شود که واقعاً همان نامهایی که شما قادر به یافتن آنها می‌باشید را به شما بدهد. ls ممکن است بعضی کاراکترها در نام فایل را با کاراکتر علامت سؤال تعویض نماید.

      2. دوم، ls سطرهای داده‌ها را بر اساس کاراکتر سطر جدید تفکیک می‌کند. به این طریق، هر تکه از اطلاعات یک فایل در یک سطر است. متأسفانه، نام فایلها نیز خودشان می‌توانند شامل سطر جدید باشند. این به معنی آنست که اگر شما فایلی در دایرکتوری جاری با نام شامل کاراکتر سطر جدید داشته باشید، کاملاً نتیجه تجزیه شما را درهم می‌ریزد و اسکریپت شکست می‌خورد!

      3. آخر از همه، اما نه کم اهمیت‌تر، قالب خروجی فرمان ‎ ls -l‎ تضمین نمی‌شود که در تمام پلاتفرم‌ها همسان باشد. برخی سیستم‌ها به طور پیش‌فرض شماره شناسایی گروه را از قلم می‌اندازند، و اثر گزینه ‎-g‎ را معکوس می‌نمایند. بعضی سیستم‌ها از دو فیلد برای زمان ویرایش و برخی از سه فیلد برای آن استفاده می‌کنند. در سیستم‌هایی که از سه فیلد استفاده می‌کنند، فیلد سوم می‌تواند سال یا یک ‎ HH:MM‎ الحاقی، نسبت به سن فایل، باشد.

      در موقعیت‌های بسیاری جایگزین‌هایی برای ls وجود دارد. اگر لازم است که شما با زمان ویرایش فایل کار کنید، به طور نمونه می‌توانید از بررسی‌های Bash استفاده کنید. اگر هیچ یک از آنها میسر نباشد، پیشنهاد می‌کنم زبان متفاوتی، همچون پرل یا python انتخاب کنید.

  • if echo "$file| fgrep .txt; then
    ls *.txt | grep story

    • هرگز نام فایل ‌ها را با grep بررسی یا فیلتر نکنید! غیر از آنکه الگوی grep شما واقعاً هوشمند باشد، این کار احتمالاً قابل اطمینان نخواهد بود.

    • در نمونه اول مثال فوق، بررسی با هر دو مورد story.txt و story.txt.exe منطبق می‌گردد. اگر الگوهایی از grep ایجاد کنید که به اندازه کافی هوشمند باشند، احتمالاً آنها به قدری زشت، حجیم و ناخوانا می‌شوند، که با این وجود نباید از آنها استفاده کنید.

    • جایگزین آن globbing نامیده می‌شود( مترجم: من در این ترجمه گاهی به جای آن کلمه«جانشینی» را به کاربرده‌‌ام). Bash یک ویژگی به نام بسط نام‌مسیر دارد. این ویژگی به شما کمک می‌کند، که تمام فایلهایی که با یک الگوی معین مطابقت دارند را به شمار آورید. همچنین، می‌توانیداز globها جهت بررسی آنکه یک نام فایل، آیا با یک الگوی معین مطابقت می‌کند، (در یک دستور case یا ‎[[‎ ) استفاده نمایید .

  • cat file | grep pattern

    • برنامه cat را برای خوراندن محتویات یک فایل منفرد به یک فیلتر به کار نبرید. cat یک ابزار مورد استفاده برای الحاق محتویات چند فایل با یکدیگر است.

    • برای تغذیه محتویات فایلی به یک پردازش، احتمالاً می‌توانید نام فایل را به عنوان شناسه تحویل برنامه مورد نظر(مانند ‎grep 'pattern/my/file‎ یا ‎sed 'expression/my/file ‎و غیره) بدهید.

    • اگر مستندات برنامه هیچ راهی برای انجام این کار تعیین نکرده است، باید از تغییر مسیر استفاده کنید (‎read column1 column2 < /my/file‎ یا ‎tr ' ' '\n< /my/file ‎و غیره).

  • for line in $(<file); do

    • از حلقه for برای خواندن سطرهای یک فایل استفاده نکنیم. به جای آن حلقه while read را به کار ببریم.

  • for number in $(seq 1 10); do

    • به خاطر خدا و به خاطر تمام مقدسات، از برنامه seq برای شمارش استفاده نکنید.

    • Bash به اندازه کافی در انجام شمارش توانمند است. نیازی به یک برنامه خارجی(مخصوصاً یک برنامه تک سکویی) برای انجام محاسبه و ارسال آن به خروجی Bash جهت تفکیک کلمه، ندارید. ترکیب دستوری for را قبلاً آموخته‌اید!

    • باید در Bash نگارش 3 به بعد، از این: ‎for number in {1..10}‎، یا در ‎Bash 2‎ از این: ‎for ((i=1i<=10i++))‎ استفاده کنید.

    • اگر شما عملاً یک جریانی از اعداد که با کاراکتر سطر جدید از هم جدا شده‌اند، هنگام بررسی ورودی می‌خواهید، این مورد را در نظر بگیرید: ‎printf '%d\n' {1..10}

  • i=`expr $i + 1>`

    • expr یک عتیقه رُم باستان است. آن را به کار نبرید.

    • این برنامه در اسکریپت‌های نوشته شده برای پوسته‌هایی با امکانات بسیار محدود، به کار می‌رفت. اساساً با استفاده از آن در حال ایجاد یک پردازش جدید هستید که برنامه C دیگری برای انجام برخی محاسبات را برایتان فراخوانی نماید و نتایج را به صورت رشته به bashتحویل بدهد. Bash تمام اینها را خودش می‌تواند خیلی سریعتر، و به طور قابل اعتمادتر (بدون تبدیل عدد به ->رشته -> به عدد) و در همه حال بهتر، انجام بدهد.

    • شما در Bash باید از این استفاده کنید: ‎let i++ ‎ یا ‎((i++))

    • حتی پوسته POSIX بورن می‌تواند محاسبات را انجام بدهد: i=$(($i+1))‎. فقط فاقد عملگر ++ و دستور‎ ((...))‎ می‌باشد(فقط عبارت جایگزینی ‎ $((...))‎ را دارد).


ادامه دارد...