خط فرمان لینوکس

ترجمه فارسی LinuxCommand.org

خط فرمان لینوکس

ترجمه فارسی LinuxCommand.org

بسط

بسط

هر گاه شما یک سطرِ فرمان تایپ می‌کنید و کلید اینتر را فشار می‌دهید، bash قبل از انجام دادن فرمان شما چند پردازش روی آن اجرا می‌کند. ما در چند موقعیت دیده‌ایم که چگونه یک رشته کاراکتر ساده، به عنوان مثال «*»، می‌تواند معنای زیادی برای پوسته داشته باشد. پردازشی که باعث این رویداد می‌گردد، بسط نامیده می‌شود. به وسیله بسط، شما موردی را تایپ می‌کنید و آن مورد قبل از عمل کردن پوسته بر روی آن، به چیز دیگری توسعه داده می‌شود. برای نمایش دادن آنکه چه هدفی از این مطلب داریم، بیایید نگاهی به فرمان echo داشته باشیم. echo یک فرمان داخلی پوسته است که یک وظیفه بسیار ساده را اجرا می‌کند. شناسه‌های متنی‌اش را در خروجی استاندارد چاپ می‌کند:

[me@linuxbox me]$ echo this is a test
this is a test

تا حدی سر راست است. هر شناسه عبور داده شده به echo نمایش داده می‌شود. بیایید مثال دیگری را امتحان کنیم:

[me@linuxbox me]$ echo *
Desktop Documents ls-output.txt Music Pictures Public Templates Videos

پس دقیقاً چه اتفاقی رخ می‌دهد؟ چرا echo این «*» را چاپ نمی‌کند؟ به طوری که از کارمان با کاراکترهای عام به یاد دارید، کاراکتر «*» به معنی انطباق با همه کاراکترها در یک نام فایل است، اما آنچه ما در بحث نخستین‌مان ندیدیم آن بود که پوسته چگونه آن را انجام می‌دهد. پاسخ ساده آن است که پوسته «*» را قبل از اینکه فرمان echo اجرا بشود به چیز دیگری بسط می‌دهد (در این نمونه، به نام فایلهای دایرکتوری کاری فعلی). وقتی کلید اینتر فشرده می‌شود، پوسته به طور خودکار همه کاراکترهای واجد شرایط در خط فرمان را قبل از اینکه فرمان اجرا شود بسط می‌دهد، بنابراین فرمان echo اصلاً «*» را ندید، بلکه نتیجه بسط یافته را دید. با آگاهی از این مطلب، ما می‌توانیم مشاهده کنیم که echo همانطور که انتظار می‌رفت عمل نموده است.

بسط نام مسیر

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

[me@linuxbox me]$ ls

Desktop
ls-output.txt
Documents Music
Pictures
Public
Templates
Videos

می‌توانستیم بسط‌های زیر را اجرا کنیم:

[me@linuxbox me]$ echo D*
Desktop Documents

و:

[me@linuxbox me]$ echo *s
Documents Pictures Templates Videos

یا حتی:

[me@linuxbox me]$ echo [[:upper:]]*
Desktop Documents Music Pictures Public Templates Videos

و نگریستن به ماورای دایرکتوری خانگی‌مان:

[me@linuxbox me]$ echo /usr/*/share
/usr/kerberos/share /usr/local/share

بسط مد

به طوری که ممکن است شما از معرفی فرمان cd به خاطر بیاورید، کاراکتر مد («~») معنای ویژه‌ای دارد. هنگامی که در ابتدای یک کلمه به کار برود، به نام دایرکتوری خانگی کاربر نامبرده، یا در صورتیکه کاربری ذکر نشده باشد، به دایرکتوری خانگی کاربر جاری، بسط داده می‌شود:

[me@linuxbox me]$ echo ~
/home/me

اگر کاربر foo یک حساب کاربری دارد، آنوقت:

[me@linuxbox me]$ echo ~foo
/home/foo

بسط حسابی

پوسته اجازه می‌دهد به وسیله بسط، محاسبه انجام بشود. این مورد به ما امکان می‌دهد اعلان پوسته را به عنوان یک ماشین حساب به کار ببریم:

[me@linuxbox me]$ echo $((2 + 2))
4

بسط حسابی این قالب را استفاده می‌کند:

   $((expression))

که در آن «expression» یک عبارت حسابی متشکل از متغیرها و عملگرهای محاسباتی است.

بسط حسابی فقط اعداد صحیح (اعداد کامل، نه اعشاری) را پشتیبانی می‌کند، اما کاملاً می‌تواند عملیات متعدد مختلفی را انجام بدهد.

در بسط حسابی فاصله‌ها با اهمیت نیستند و عبارت می‌تواند تو در تو باشد. به عنوان مثال، برای پنج به توان دو ضربدر سه:

[me@linuxbox me]$ echo $(($((5**2)) * 3))
75

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

[me@linuxbox me]$ echo $(((5**2) * 3))
75

این هم یک مثال با استفاده از عملگرهای تقسیم و باقیمانده. به اثر تقسیم صحیح توجه کنید:

[me@linuxbox me]$ echo Five divided by two equals $((5/2))
Five divided by two equals 2
[me@linuxbox me]$ echo with $((5%2)) left over.
with 1 left over.

بسط ابرو

گویا عجیب‌ترین بسط، بسط ابرو نامیده می‌شود. با این بسط، شما می‌توانید از یک الگوی شامل ابروها چندین رشته متن خلق کنید. اکنون یک مثال:

[me@linuxbox me]$ echo Front-{A,B,C}-Back
Front-A-Back Front-B-Back Front-C-Back

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

[me@linuxbox me]$ echo Number_{1..5}
Number_1 Number_2 Number_3 Number_4 Number_5

یک محدوده از حروف با ترتیب وارونه:

[me@linuxbox me]$ echo {Z..A}
Z Y X W V U T S R Q P O N M L K J I H G F E D C B A

بسط ابرو می‌تواند تو در تو باشد:

[me@linuxbox me]$ echo a{A{1,2},B{3,4}}b
aA1b aA2b aB3b aB4b

برای چه کاری مناسب است؟ رایج‌ترین کاربرد آن برای ساختن فهرست‌هایی از فایلها یا دایرکتوری‌هایی است که باید ایجاد گردند. برای مثال، اگر شما یک عکاس بودید و مجموعه بزرگی از تصاویر داشتید که می‌خواستید آنها را نسبت به سال و ماه مرتب کنید، اولین کاری که شاید شما انجام بدهید ایجاد یک گروه دایرکتوری‌های نامگذاری شده در قالب «سال-ماه» است. در این روش، نام دایرکتوری‌ها به ترتیب تاریخی رخداد مرتب خواهند شد. شما می‌توانستید لیست کامل دایرکتوری‌ها را به تفصیل تایپ کنید، اما این کارِ خیلی زیادی است و متمایل به خطا نیز هست. به جای آن، شما می‌توانستید این مورد را انجام بدهید:

[me@linuxbox me]$ mkdir Photos
[me@linuxbox me]$ cd Photos
[me@linuxbox Photos]$ mkdir {2007..2009}-0{1..9} {2007..2009}-{10..12}
[me@linuxbox Photos]$ ls

2007-01 2007-07 2008-01 2008-07 2009-01 2009-07
2007-02 2007-08 2008-02 2008-08 2009-02 2009-08
2007-03 2007-09 2008-03 2008-09 2009-03 2009-09
2007-04 2007-10 2008-04 2008-10 2009-04 2009-10
2007-05 2007-11 2008-05 2008-11 2009-05 2009-11
2007-06 2007-12 2008-06 2008-12 2009-06 2009-12

نسبتاً ماهرانه!

بسط پارامتر

ما در این درس فقط می‌خواهیم به طور خلاصه بسط پارامتر را مطرح کنیم، اما در آینده بیشتر آن را پوشش خواهیم داد. این خصیصه‌ای است که بیشتر از آنکه به طور مستقیم در خط فرمان سودمند باشد، در اسکریپت‌های پوسته مفید است. بسیاری از امکانات آن در ارتباط با توانایی سیستم برای ذخیره قطعه‌های کوچکی از داده‌ها و اختصاص یک نام به هر قطعه است. بسیاری از چنین قطعه‌هایی، که نام شایسته‌تر آنها متغیراست، برای بررسی شما در دسترس هستند. برای مثال، متغیری به نام «USER» شامل نام کاربری شما است. برای فراخوانی بسط پارامتر و آشکارسازی محتوای آن شما باید به این طریق عمل کنید:

[me@linuxbox me]$ echo $USER
me

برای دیدن فهرستی از متغیرهای در دسترس، این را امتحان کنید:

[me@linuxbox me]$ printenv | less

ممکن است شما متوجه شده‌اید که با انواع دیگر بسط، اگر یک الگو را اشتباه تایپ کنید، بسط صورت نخواهد گرفت و فرمان echo به سادگی الگوی تایپ شدهِ اشتباه را نمایش خواهد داد. با بسط پارامتر، در صورتیکه شما املای نام متغیر را اشتباه کنید، باز هم بسط انجام خواهد شد، اما به یک رشته تهی:

[me@linuxbox me]$ echo $SUER
[me@linuxbox ~]$

جایگزینی فرمان

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

[me@linuxbox me]$ echo $(ls)
Desktop Documents ls-output.txt Music Pictures Public Templates Videos

یکی از موارد مورد پسند من چیزی مانند این است:

[me@linuxbox me]$ ls -l $(which cp)
-rwxr-xr-x 1 root root 71516 2007-12-05 08:58 /bin/cp

در اینجا ما نتایج which cp را به عنوان یک شناسه به فرمان ls عبور داده‌ایم، به موجب آن، فهرستی از برنامه cp را بدون دانستن نام مسیر کامل آن به دست می‌آوریم. ما فقط به فرمانهای ساده محدود نیستیم. خط لوله‌های کامل هم می‌توانند استفاده شوند (تنها بخشی از خروجی نشان داده شده):

[me@linuxbox me]$ file $(ls /usr/bin/* | grep bin/zip)

/usr/bin/bunzip2:
/usr/bin/zip:      ELF 32-bit LSB executable, Intel 80386, version 1 
(SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped
/usr/bin/zipcloak: ELF 32-bit LSB executable, Intel 80386, version 1
(SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped
/usr/bin/zipgrep:  POSIX shell script text executable
/usr/bin/zipinfo:  ELF 32-bit LSB executable, Intel 80386, version 1
(SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped
/usr/bin/zipnote:  ELF 32-bit LSB executable, Intel 80386, version 1
(SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped
/usr/bin/zipsplit: ELF 32-bit LSB executable, Intel 80386, version 1
(SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped

در این مثال، نتایج خط لوله لیست شناسه‌های فرمان file شده‌اند. یک ترکیب دستوری پیشنهادی در برنامه‌های پوسته قدیمی‌تر برای جایگزینی فرمان هست که در bash نیز پشتیبانی شده است. آن ترکیب به جای علامت دلار و پرانتزها از نقل‌قول‌های وارونه استفاده می‌کند:

[me@linuxbox me]$ ls -l `which cp`
-rwxr-xr-x 1 root root 71516 2007-12-05 08:58 /bin/cp

نقل‌قول

اکنون که دیده‌ایم پوسته به روش‌های بسیاری می‌تواند بسط‌ها را انجام بدهد، وقت آن است که یاد بگیریم، ما چطور می‌توانیم آن را کنترل نماییم. این مثال را در نظر بگیرید:

[me@linuxbox me]$ echo this is a     test
this is a test

یا:

[me@linuxbox me]$ [me@linuxbox ~]$ echo The total is $100.00
The total is 00.00

در مثال نخست، تفکیک کلمه توسط پوسته فضاهای سفید اضافی در فهرست شناسه‌های فرمان echo را پاک کرده است. در مثال دوم، بسط پارامتر یک رشته تهی برای مقدار ‎$1‎ جایگزین نمود زیرا یک متغیر تعریف نشده بود. پوسته برای موقوف کردن انتخابی بسط‌های ناخواسته ساز و کاری به نام نقل‌قول فراهم می‌کند.

نقل‌قول‌های دوگانه

اولین نوع نقل‌قولی که به آن خواهیم پرداخت نقل‌قول دوگانه است، تمام کاراکترهای خاص مورد استفاده پوسته داخل نقل‌قول دوگانه معنای ویژه خود را از دست می‌دهند و به عنوان کاراکترهای معمولی با آنها رفتار می‌گردد. موارد استثنا عبارتند از $، \ و ` (نقل‌قول برعکس). این بدان معنی است که تفکیک کلمه، بسط نام مسیر، بسط مد، و بسط ابرو خاموش می‌شوند، اما بسط پارامتر، بسط حسابی، و جایگزینی فرمان بازهم اجرا می‌گردند. با استفاده از نقل‌قول‌های دوگانه، ما می‌توانیم نام‌فایلهای شامل فاصله‌های تعبیه شده را حریف بشویم. فرض کنیم شما قربانی بداقبالِ فایلی به نام ‎two words.txt‎ بودید. اگر شما سعی در استفاده از این فایل در خط فرمان می‌نمودید، تفکیک کلمه باعث می‌گردید با این نام به جای یک شناسه منفردِ مطلوب، به عنوان دو شناسه جداگانه رفتار بشود:

[me@linuxbox me]$ ls -l two words.txt

ls: cannot access two: No such file or directory
ls: cannot access words.txt: No such file or directory

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

[me@linuxbox me]$ ls -l "two words.txt"
-rw-rw-r-- 1 me me 18 2008-02-20 13:03 two words.txt
[me@linuxbox me]$ mv "two words.txt" two_words.txt

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

[me@linuxbox me]$ echo "$USER $((2+2)) $(cal)"

me 4
February 2008
Su Mo Tu We Th Fr Sa
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29

ما باید زمان کوتاهی را به تاثیر نقل‌قول‌های دوگانه بر جایگزینی فرمان بپردازیم. ابتدا بیایید کمی عمیق‌تر نگاه کنیم که تفکیک کلمه چگونه کار می‌کند. در مثال قدیمی‌تر، ما دیدیم در زدودن فاصله‌های اضافه از متن، تفکیک کلمه چگونه ظاهر می‌شود:

[me@linuxbox me]$ echo this is a     test
this is a test

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

[me@linuxbox me]$ echo "this is a     test"
this is a     test

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

[me@linuxbox me]$ echo $(cal)
February 2008 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
[me@linuxbox me]$ echo "$(cal)"

February 2008
Su Mo Tu We Th Fr Sa
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29

در نمونه نخست، جایگزینی فرمان نقل‌قولی نشده به یک سطر فرمانِ سی و هشت شناسه‌ای منجر می‌شود. در دومی، یک سطر فرمان با یک شناسه که شامل فاصله‌ها و سطرهای جدید جاسازی شده است.

نقل‌قول‌های منفرد

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

[me@linuxbox me]$ echo text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
text /home/me/ls-output.txt a b foo 4 me
[me@linuxbox me]$ echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER"
text ~/*.txt {a,b} foo 4 me
[me@linuxbox me]$ echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'
text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER

به طوریکه می‌توانید مشاهده کنید، با هر مرحله بعدیِ نقل‌قول کردن، بسط‌های بیشتر و بیشتری خاموش می‌گردند.

کاراکترهای معاف کردن (Escaping)

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

[me@linuxbox me]$ echo "The balance for user $USER is: \$5.00"
The balance for user me is: $5.00

استفاده از معاف کردن برای زدودن معنای ویژه یک کاراکتر در نام یک فایل نیز متداول است. برای مثال، استفاده از کاراکترهایی در نام فایل که به طور معمول برای پوسته دارای معنای خاص هستند، امکان‌پذیر است. اینها می‌توانند شامل $، !، &، و دیگران باشند. برای قرار دادن یک کاراکتر خاص در نام یک فایل می‌توانید اینطور عمل کنید:

[me@linuxbox me]$ mv bad\&filename good_filename

برای اجازه دادن به حضور یک کاراکتر \ با تایپ کردن به این شکل \\ آن را معاف کنید(از معنای خاص). توجه نمایید که داخل نقل‌قول منفرد \ معنای ویژه را از دست می‌دهد و به عنوان یک کاراکتر معمولی عمل می‌کند.

شگردهای بیشتر با Backslash

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

ls -r
ls --reverse

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

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

ls -l \
   --reverse \
   --human-readable \
   --full-time

کاربرد backslash به این روش به ما امکان می‌دهد سطرهای جدید را در فرمان خود درج کنیم. توجه نمایید که برای آنکه این ترفند کار کند، سطرجدید باید به طور بدون فاصله پس از backslash تایپ شود. اگر شما یک فاصله پس از backslash قرار بدهید، کاراکتر فاصله صرفنظر خواهد شد، نه سطرجدید. Backslashها برای درج کاراکترهای خاص داخل متن ما نیز به کار می‌روند. اینها کاراکترهای گریزِ backslash نامیده می‌شوند. این هم برخی از موارد رایج:

کاراکتر گریز

نام

استفاده‌های امکان‌پذیر

\n

سطرجدید

افزودن سطرهای خالی به متن

\t

tab

درج tabهای افقی به متن

\a

هشدار

ایجاد صدای بوق کوتاه ترمینال

\\

backslash

یک \ درج می‌کند

\f

تغذیه کاغذ

فرستادن این کاراکتر به چاپگرِ شما صفحه رابیرون می‌دهد

استفاده از این کاراکترهای گریزِ backslash بسیار رایج است. این اندیشه ابتدا در زبان برنامه‌نویسی C ظاهر گردید. امروزه، شل، ‎C++‎، پرل، پایتون، awk، ‏tcl، و دیگر زبانهای برنامه‌نویسی این تدبیر را به کار می‌برند. کاربرد فرمان echo با گزینه ‎-e‎ نمایش دادن آنها را برای ما امکان‌پذیر می‌کند:

[me@linuxbox me]$ echo -e "Inserting several blank lines\n\n\n"
Inserting several blank lines



[me@linuxbox me]$ echo -e "Words\tseparated\tby\thorizontal\ttabs."

Words separated   by  horizontal  tabs
[me@linuxbox me]$ echo -e "\aMy computer went \"beep\"."

My computer went "beep".

[me@linuxbox me]$ echo -e "DEL C:\\WIN2K\\LEGACY_OS.EXE"

DEL C:\WIN2K\LEGACY_OS.EXE