FISH-TUTORIAL(1) fish-shell FISH-TUTORIAL(1)

fish-tutorial - آموزش تعاملی پوسته فیش

پوسته fish یک پوسته خط فرمان مجهز و کامل (مانند bash یا zsh) است که هوشمند و کاربرپسند طراحی شده است. فیش از قابلیت‌های قدرتمندی نظیر برجسته‌سازی نحو (Syntax Highlighting)، پیشنهادهای خودکار (Autosuggestions) و تکمیل تب (Tab Completions) پشتیبانی می‌کند که همگی بدون نیاز به هیچ‌گونه پیکربندی یا آموزش پیچیده، بلافاصله کار می‌کنند.

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

پس از نصب، برای آزمایش کافی است دستور fish را در پوسته جاری خود تایپ و اجرا کنید!

با اعلان استاندارد فیش روبرو خواهید شد که نشان می‌دهد همه‌چیز آماده است و می‌توانید کار با فیش را شروع کنید:

> fish
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
you@hostname ~>

اعلانی که در بالا مشاهده می‌کنید، خط اعلان پیش‌فرض فیش است: نام کاربری، نام میزبان و دایرکتوری کاری شما را نمایش می‌دهد. شما می‌توانید آن را سفارشی‌سازی کنید؛ برای راهنمایی به بخش تغییر خط اعلان مراجعه نمایید <#prompt>.

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

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

اگر درک خوبی از سایر پوسته‌ها دارید و می‌خواهید تفاوت‌های فیش را بدانید، عبارت کلیدی unlike other shells (برخلاف سایر پوسته‌ها) را در مستندات جستجو کنید که برای اشاره به تفاوت‌های مهم استفاده شده است.

همچنین برای یک مرور سریع بر تفاوت‌ها با سایر پوسته‌ها مانند بش، به بخش فیش برای کاربران بش مراجعه کنید <>.

برای توضیحات کامل و تفصیلی درباره نحوه استفاده تعاملی از فیش، به استفاده تعاملی مراجعه کنید <>.

برای شرح جامع زبان اسکریپت‌نویسی فیش، به زبان فیش مراجعه کنید <>.

فیش دستورات را مانند سایر پوسته‌ها اجرا می‌کند: ابتدا نام دستور را می‌نویسید و در ادامه آرگومان‌های آن را ذکر می‌کنید. فاصله‌ها به عنوان جداکننده عمل می‌کنند:

> echo hello world
hello world

این کار دستور echo را با آرگومان‌های hello و world اجرا می‌کند. در این مثال، نتیجه مانند ارسال یک تک‌آرگومان hello world است، اما در بسیاری از موارد تفاوت دارد. اگر نیاز دارید آرگومانی حاوی فاصله ارسال کنید، می‌توانید آن فاصله را با بک‌اسلش اسکیپ کنید <#escapes> یا با کوتیشن تکی یا جفتی محصور نمایید <#quotes>:

> mkdir My\ Files
# Makes a directory called "My Files", with a space in the name
> cp ~/Some\ File 'My Files'
# Copies a file called "Some File" in the home directory to "My Files"
> ls "My Files"
Some File

برای باز کردن راهنمای فیش در مرورگر وب دستور help و برای باز کردن صفحه در قالب man (مانند fish-language) دستور man را اجرا کنید. همچنین می‌توانید برای دستوری مشخص درخواست راهنما کنید؛ مثلاً help set در مرورگر وب یا man set در محیط ترمینال.

> man set
set - handle shell variables
  Synopsis...

برای دسترسی مستقیم به این بخش از دستور help getting-help استفاده کنید.

این دستورات فقط برای مستندات اختصاصی خود فیش و دستورات داخلی آن (builtins) کار می‌کنند. برای سایر دستورات سیستم، هر ابزار مستندات خودش را ارائه می‌دهد که معمولاً در سیستم man قرار دارد؛ به عنوان مثال دستور man ls توضیحات مربوط به دستور ls سیستم شما را نمایش می‌دهد.

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

> /bin/mkd

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

> /bin/mkdir

مسیرهای فایل معتبر هنگام تایپ با خط زیرین (Underline) مشخص می‌شوند:

> cat ~/somefi

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

این رنگ‌ها و بسیاری تنظیمات دیگر را می‌توان با اجرای fish_config یا با تغییر مستقیم متغیرهای رنگ <#variables-color> سفارشی‌سازی کرد.

برای مثال، اگر می‌خواهید (تقریباً) تمامی رنگ‌آمیزی‌ها را غیرفعال کنید:

fish_config theme choose none

این دستور پوسته گرافیکی "none" (هیچ‌کدام) را انتخاب می‌کند. برای مشاهده تمامی پوسته‌ها:

fish_config theme show

تنها با اجرای دستور fish_config یک رابط کاربری تحت وب در مرورگر باز می‌شود که به شما امکان انتخاب از میان پوسته‌های موجود را می‌دهد.

هنگام تایپ کردن، فیش ادامه دستورات پیشنهادی را به رنگ خاکستری در سمت راست مکان‌نما نمایش می‌دهد؛ برای مثال:

> /bin/hostname

فیش مسیرها و گزینه‌ها را به خوبی می‌شناسد:

> grep --ignore-case

و همچنین تاریخچه دستورات را به یاد دارد. کافی است یک دستور را یک‌بار تایپ کرده باشید تا با وارد کردن تنها چند حرف نخست، بتوانید مجدداً آن را فراخوانی کنید:

> rsync -avze ssh . myname@somelonghost.com:/some/long/path/doo/dee/doo/dee/doo

برای پذیرفتن پیشنهاد خودکار، کلید راست (→) یا ترکیب کلیدهای ctrl-f را فشار دهید. برای پذیرفتن تنها یک کلمه از پیشنهاد خودکار، کلیدهای alt-راست (→) را بزنید. اگر پیشنهاد مورد نظر شما نیست، کافی است به تایپ خود ادامه داده و آن را نادیده بگیرید.

اگر مایل به استفاده از پیشنهادهای خودکار نیستید، می‌توانید با تنظیم متغیر $fish_autosuggestion_enabled روی مقدار 0 آن‌ها را غیرفعال کنید:

set -g fish_autosuggestion_enabled 0

مجموعه غنی و قدرتمندی از قابلیت‌های تکمیل خودکار با کلید تب به صورت پیش‌فرض و بی‌درنگ کار می‌کنند.

کلید tab را فشار دهید تا فیش سعی کند نام دستور، آرگومان یا مسیر مورد نظر را کامل کند:

> /pritab => /private/

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

> ~/stuff/stab
~/stuff/script.sh  (command)  ~/stuff/sources/  (directory)

با فشردن مجدد کلید تب می‌توانید بین گزینه‌های پیشنهادی جابه‌جا شوید. بخش داخل پرانتز در مثال بالا (مانند "command" به معنی دستور و "directory" به معنی دایرکتوری) توصیف تکمیل خودکار است که راهنمایی کوتاهی درباره نوع آن آرگومان ارائه می‌دهد.

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

> git merge prtab => git merge prompt_designer
> git checkout btab
builtin_list_io_merge (Branch)  builtin_set_color (Branch) busted_events (Tag)

کلید تب را فشار دهید و ببینید فیش چه کارهایی می‌تواند انجام دهد!

مانند سایر پوسته‌ها، علامت دلار که پس از آن نام یک متغیر بیاید، با مقدار آن متغیر جایگزین می‌شود:

> echo My home directory is $HOME
My home directory is /home/tutorial

این فرآیند به عنوان جایگزینی متغیر (Variable Substitution) شناخته می‌شود و در داخل کوتیشن دوتایی (Double Quotes) نیز اعمال می‌شود، اما در کوتیشن تکی (Single Quotes) انجام نمی‌گیرد:

> echo "My current directory is $PWD"
My current directory is /home/tutorial
> echo 'My current directory is $PWD'
My current directory is $PWD

برخلاف سایر پوسته‌ها، فیش دارای یک دستور معمولی برای مقداردهی متغیرها است: دستور set، که نام متغیر و سپس مقدار آن را دریافت می‌کند.

> set name 'Mister Noodle'
> echo $name
Mister Noodle

(به کوتیشن‌ها دقت کنید: بدون آن‌ها، کلمات Mister و Noodle به عنوان دو آرگومان مجزا در نظر گرفته می‌شدند و متغیر $name به یک لیست دو عضوی تبدیل می‌شد.)

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

> mkdir $name
> ls
Mister Noodle

در بش (bash)، این دستور دو دایرکتوری با نام‌های "Mister" و "Noodle" ایجاد می‌کرد. در فیش، تنها یک دایرکتوری ایجاد می‌شود: متغیر دارای مقدار "Mister Noodle" بود، بنابراین همان مقدار با تمام فاصله‌هایش به عنوان یک تک‌آرگومان به دستور mkdir ارسال شد.

می‌توانید یک متغیر را با گزینه -e یا --erase حذف (پاک) کنید:

> set -e MyVariable
> env | grep MyVariable
(no output)

برای اطلاعات بیشتر، به گسترش متغیرها مراجعه کنید <#expand-variable>.

گاهی نیاز است یک متغیر در دسترس دستورات خارجی قرار گیرد؛ این کار اغلب برای اعمال تنظیمات انجام می‌شود. برای مثال بسیاری از برنامه‌ها مانند git یا man متغیر $PAGER را می‌خوانند تا صفحه‌بندی‌کننده دلخواه شما (برنامه‌ای که امکان اسکرول متن را می‌دهد) را شناسایی کنند. متغیرهای دیگری که به این شکل استفاده می‌شوند شامل $BROWSER، $LANG (برای پیکربندی زبان سیستم) و $PATH هستند. توجه داشته باشید که نوشتن این متغیرها با حروف بزرگ صرفاً یک قرارداد مرسوم است.

برای ارسال یک متغیر به یک دستور خارجی، آن متغیر باید صادر (Export) شود. این کار با افزودن یک فلگ به دستور set انجام می‌شود: فلگ --export یا به اختصار -x.

> set -x MyVariable SomeValue
> env | grep MyVariable
MyVariable=SomeValue

همچنین می‌توان یک متغیر را با گزینه --unexport یا -u از حالت صادرشده خارج کرد.

این سازوکار در جهت عکس نیز عمل می‌کند! اگر فیش توسط فرآیند دیگری اجرا شود، متغیرهای صادرشده والد خود را به ارث می‌برد. بنابراین اگر شبیه‌ساز ترمینال شما فیش را اجرا کند و متغیر $LANG را روی en_US.UTF-8 صادر کرده باشد، فیش آن تنظیم را دریافت خواهد کرد. هر فرآیندی هم که شبیه‌ساز ترمینال شما را اجرا کرده، متغیرهایی به آن داده که به فیش منتقل می‌شوند، مگر اینکه صریحاً تصمیم به عدم ارسال بگیرد. به این ترتیب است که فیش معمولاً مقادیر مواردی مانند $LANG، $PATH و $TERM را بدون نیاز به تعریف مجدد توسط شما دریافت می‌کند.

متغیرهای صادرشده می‌توانند محلی (Local)، سراسری (Global) یا فراگیر (Universal) باشند - مفهوم صادرشدن (Exported) یک حوزه متغیر نیست <#variables-scope>! معمولاً آن‌ها را با دستور set -gx MyVariable SomeValue به صورت سراسری تعریف می‌کنند.

برای اطلاعات بیشتر، به صادر کردن متغیرها مراجعه نمایید <#variables-export>.

دستور set در بالا از کوتیشن استفاده کرد تا اطمینان حاصل شود که Mister Noodle یک آرگومان واحد است. اگر دو آرگومان بود، آن‌گاه name یک لیست با طول ۲ می‌شد. در واقع، تمام متغیرها در فیش در اصل لیست‌هایی هستند که می‌توانند شامل هر تعداد مقدار یا حتی بدون هیچ مقداری باشند.

برخی متغیرها مانند $PWD تنها یک مقدار دارند. طبق قرارداد، ما از «مقدار» آن متغیر صحبت می‌کنیم، اما منظور واقعی ما اولین (و تنها) مقدار آن در لیست است.

سایر متغیرها، مانند $PATH، واقعاً دارای چندین مقدار هستند. در حین گسترش متغیر، متغیر به چندین آرگومان مجزا تبدیل می‌شود:

> echo $PATH
/usr/bin /bin /usr/sbin /sbin /usr/local/bin

متغیرهایی که نام آن‌ها با "PATH" خاتمه می‌یابد، به طور خودکار بر اساس دونقطه (Colon) به لیست تبدیل می‌شوند. این متغیرها هنگام صادر شدن به زیردستورات مجدداً با دونقطه به هم متصل می‌گردند. این کار برای سازگاری با سایر ابزارها است که انتظار دارند متغیر $PATH با دونقطه جدا شده باشد. همچنین می‌توانید این رفتار را به طور صریح با set --path به یک متغیر اضافه یا با set --unpath حذف کنید.

لیست‌ها نمی‌توانند حاوی لیست‌های دیگر باشند؛ هیچ‌گونه تودرتویی یا بازگشتی وجود ندارد. یک متغیر صرفاً یک لیست از رشته‌ها است و بس.

برای به دست آوردن طول یک لیست از دستور count استفاده کنید:

> count $PATH
5

می‌توانید با مقداردهی متغیر با خودش به همراه آرگومان‌های جدید، به ابتدا یا انتهای یک لیست مقادیری را اضافه کنید. در اینجا مسیر /usr/local/bin را به انتهای $PATH اضافه می‌کنیم:

> set PATH $PATH /usr/local/bin

می‌توانید با استفاده از براکت‌ها به عناصر منفرد لیست دسترسی داشته باشید. شماره‌گذاری اندیس‌ها از ابتدای لیست با 1 و از انتهای لیست با -1 آغاز می‌شود:

> echo $PATH
/usr/bin /bin /usr/sbin /sbin /usr/local/bin
> echo $PATH[1]
/usr/bin
> echo $PATH[-1]
/usr/local/bin

همچنین می‌توانید به محدوده‌ای از عناصر که با نام برش‌ها ("slices") شناخته می‌شوند دسترسی پیدا کنید:

> echo $PATH[1..2]
/usr/bin /bin
> echo $PATH[-1..2]
/usr/local/bin /sbin /usr/sbin /bin

می‌توانید با یک حلقه for روی یک لیست (یا یک برش از آن) پیمایش انجام دهید:

for val in $PATH
  echo "entry: $val"
end
# Will print:
# entry: /usr/bin/
# entry: /bin
# entry: /usr/sbin
# entry: /sbin
# entry: /usr/local/bin

یک نکته بسیار کاربردی این است که می‌توانید از لیست‌ها مانند گسترش آکولاد (Brace Expansion) استفاده کنید <#expand-brace>. اگر رشته دیگری را به یک لیست بچسبانید، آن رشته با تک‌تک عناصر لیست ترکیب خواهد شد:

> set mydirs /usr/bin /bin
> echo $mydirs/fish # this is just like {/usr/bin,/bin}/fish
/usr/bin/fish /bin/fish

این رفتار همچنین به این معنی است که اگر لیست خالی باشد، هیچ آرگومانی تولید نخواهد شد:

> set empty # no argument
> echo $empty/this_is_gone # prints an empty line

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

برای اطلاعات بیشتر، به بخش لیست‌ها مراجعه کنید <#variables-lists>. برای توضیحات تکمیلی درباره ترکیب لیست‌ها با رشته‌ها (یا سایر لیست‌ها)، به ضرب دکارتی <#cartesian-product> و گسترش متغیرها <#expand-variable> مراجعه نمایید.

فیش از نویسه عام آشنای ستاره * پشتیبانی می‌کند. برای مثال برای فهرست کردن تمام فایل‌های JPEG:

> ls *.jpg
lena.jpg
meena.jpg
santa maria.jpg

می‌توانید از چندین نویسه عام به طور همزمان استفاده کنید:

> ls l*.p*
lena.png
lesson.pdf

نویسه عام بازگشتی ** دایرکتوری‌ها را به صورت بازگشتی جستجو می‌کند:

> ls /var/**.log
/var/log/system.log
/var/run/sntp.log

اگر این پیمایش در دایرکتوری‌ها زمان زیادی طول کشید، می‌توانید با فشردن کلیدهای ctrl-c از آن خارج شوید.

برای اطلاعات بیشتر، به بخش نویسه‌های عام مراجعه کنید <#expand-wildcard>.

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

> echo hello world | wc
      1       2      12

ورودی استاندارد (stdin) و خروجی استاندارد (stdout) را می‌توان با کاراکترهای آشنای < و > تغییر مسیر داد. خروجی خطای استاندارد (stderr) نیز با 2> هدایت می‌شود.

> grep fish < /etc/shells > ~/output.txt 2> ~/errors.txt

برای هدایت همزمان خروجی استاندارد و خروجی خطا به یک فایل، می‌توانید از &> استفاده کنید:

> make &> make_output.txt

برای اطلاعات بیشتر، به تغییر مسیرهای ورودی و خروجی <#redirects> و پایپ‌ها <#pipes> مراجعه فرمایید.

جایگزینی دستور از خروجی یک دستور به عنوان آرگومان برای دستوری دیگر استفاده می‌کند. برخلاف سایر پوسته‌ها، فیش از بک‌تیک `` برای جایگزینی دستور استفاده نمی‌کند؛ در عوض از پرانتز با یا بدون علامت دلار استفاده می‌کند:

> echo In (pwd), running $(uname)
In /home/tutorial, running FreeBSD

یک الگوی بسیار رایج، ذخیره خروجی یک دستور در یک متغیر است:

> set os (uname)
> echo $os
Linux

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

> touch "testing_$(date +%s).txt"
> ls *.txt
testing_1360099791.txt

برخلاف سایر پوسته‌ها، فیش خروجی جایگزینی دستور را بر روی هر فاصله خالی (مانند space یا tab) تفکیک نمی‌کند، بلکه تنها بر روی خطوط جدید (Newline) می‌شکند. معمولاً این رفتار کمک بزرگی است، زیرا دستورات یونیکس به صورت خط به خط عمل می‌کنند. اما گاهی اوقات در دستوراتی مانند pkg-config که چندین آرگومان را روی یک خط چاپ می‌کنند، ممکن است نیاز به تفکیک روی فاصله باشد. برای تقسیم خروجی بر روی فاصله‌ها نیز، از دستور string split استفاده کنید.

> printf '%s\n' (pkg-config --libs gio-2.0)
-lgio-2.0 -lgobject-2.0 -lglib-2.0
> printf '%s\n' (pkg-config --libs gio-2.0 | string split -n " ")
-lgio-2.0
-lgobject-2.0
-lglib-2.0

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

> echo "first line
second line" > myfile
> set myfile "$(cat myfile)"
> printf '|%s|' $myfile
|first line
second line|

برای اطلاعات بیشتر، به بخش جایگزینی دستور مراجعه کنید <#expand-command-substitution>.

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

برای نوشتن آن‌ها در یک خط، از علامت نقطه‌ویرگول (";") استفاده کنید. این یعنی دو مثال زیر دقیقاً معادل یکدیگرند:

echo fish; echo chips
# or
echo fish
echo chips

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

هنگامی که یک دستور به کار خود پایان می‌دهد، یک کد وضعیت خروج به عنوان یک عدد صحیح غیرمنفی (یک عدد حسابی بزرگتر یا مساوی 0) برمی‌گرداند.

برخلاف سایر پوسته‌ها، فیش وضعیت خروج آخرین دستور را در متغیر $status ذخیره می‌کند و نه در $?.

> false
> echo $status
1

این کد نشان می‌دهد اجرای دستور چگونه پیش رفته است - مقدار 0 معمولاً به معنای موفقیت است، در حالی که سایر مقادیر نشان‌دهنده انواع خطا هستند. برای نمونه دستور داخلی set --query در فیش، تعداد متغیرهای استعلام‌شده‌ای که مقداردهی نشده بودند را برمی‌گرداند؛ یعنی set --query PATH معمولاً 0 برمی‌گرداند و set --query arglbargl boogagoogoo مقدار 2 برمی‌گرداند.

همچنین یک متغیر لیستی با نام $pipestatus برای ذخیره وضعیت‌های خروج [1] فرآیندها در یک پایپ وجود دارد.

برای اطلاعات بیشتر، به متغیر وضعیت مراجعه کنید <#variables-status>.

[1]
یا به تعبیر دیگر "stati" یا "statūs" اگر از روم باستان سفر در زمان کرده‌اید یا به عنوان معلم زبان لاتین کار می‌کنید

فیش از عملگرهای آشنای && و || برای ترکیب دستورات و ! برای نقیض کردن آن‌ها پشتیبانی می‌کند:

> ./configure && make && sudo make install

در این مثال، make تنها در صورتی اجرا می‌شود که ./configure با موفقیت به پایان برسد (مقدار 0 برگرداند)، و sudo make install نیز تنها در صورتی اجرا می‌شود که هر دو دستور ./configure و make موفقیت‌آمیز باشند.

فیش همچنین از دستورات and <>، or <> و not <> پشتیبانی می‌کند. دو مورد اول تعدیل‌کننده‌های شغل (Job Modifiers) هستند و اولویت کمتری دارند. نمونه کاربرد:

> cp file1 file1_bak && cp file2 file2_bak; and echo "Backup successful"; or echo "Backup failed"
Backup failed

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

cp file1 file1_bak && cp file2 file2_bak
and echo "Backup successful"
or echo "Backup failed"

برای اجرای مشروط کد بر اساس وضعیت خروج یک دستور، از دستورات if <> و else <> استفاده کنید:

if grep fish /etc/shells
    echo Found fish
else if grep bash /etc/shells
    echo Found bash
else
    echo Got nothing
end

برای مقایسه رشته‌ها، اعداد یا بررسی ویژگی‌های فایل (مانند وجود فایل یا دسترسی نوشتن و غیره)، از دستور test <> استفاده نمایید؛ مانند:

if test "$fish" = "flounder"
    echo FLOUNDER
end
# or
if test "$number" -gt 5
    echo $number is greater than five
else
    echo $number is five or less
end
# or
# This test is true if the path /etc/hosts exists
# - it could be a file or directory or symlink (or possibly something else).
if test -e /etc/hosts
    echo We most likely have a hosts file
else
    echo We do not have a hosts file
end

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

if command -sq fish; and grep fish /etc/shells
    echo fish is installed and configured
end

برای شرط‌های پیچیده‌تر، از begin <> و end <> برای گروه‌بندی بخش‌های شرط استفاده کنید.

همچنین ساختار چندشاخه switch <> در فیش وجود دارد:

switch (uname)
case Linux
    echo Hi Tux!
case Darwin
    echo Hi Hexley!
case FreeBSD NetBSD DragonFly
    echo Hi Beastie!
case '*'
    echo Hi, stranger!
end

همان‌طور که مشاهده می‌کنید، دستور case <> مانند برخی زبان‌ها به شاخه‌های بعدی سرریز (fall through) نمی‌کند و می‌تواند چندین آرگومان یا نویسه‌های عام (داخل کوتیشن) را بپذیرد.

برای اطلاعات بیشتر، به بخش شرط‌ها مراجعه کنید <#syntax-conditional>.

یک تابع در فیش، لیستی از دستورات است که می‌تواند به طور اختیاری آرگومان‌هایی را نیز بپذیرد. برخلاف سایر پوسته‌ها، آرگومان‌ها در «متغیرهای شماره‌گذاری‌شده» مانند $1 قرار نمی‌گیرند، بلکه در یک لیست واحد به نام $argv ذخیره می‌شوند. برای تعریف یک تابع، از دستور داخلی function <> استفاده کنید:

function say_hello
    echo Hello $argv
end
say_hello
# prints: Hello
say_hello everybody!
# prints: Hello everybody!

برخلاف سایر پوسته‌ها، فیش دستور نام مستعار (alias) یا نحو ویژه‌ای برای خط اعلان ندارد؛ بلکه توابع جای آن‌ها را می‌گیرند. [2]

می‌توانید با دستور داخلی functions <> نام تمامی توابع را مشاهده کنید (به جمع بودن کلمه دقت فرمایید!). فیش به طور پیش‌فرض دارای توابع متعددی است:

> functions
N_, abbr, alias, bg, cd, cdh, contains_seq, dirh, dirs, disown, down-or-search, edit_command_buffer, export, fg, fish_add_path, fish_breakpoint_prompt, fish_clipboard_copy, fish_clipboard_paste, fish_config, fish_default_key_bindings, fish_default_mode_prompt, fish_git_prompt, fish_hg_prompt, fish_hybrid_key_bindings, fish_indent, fish_is_root_user, fish_job_summary, fish_key_reader, fish_md5, fish_mode_prompt, fish_npm_helper, fish_opt, fish_print_git_action, fish_print_hg_root, fish_prompt, fish_sigtrap_handler, fish_svn_prompt, fish_title, fish_update_completions, fish_vcs_prompt, fish_vi_cursor, fish_vi_key_bindings, funced, funcsave, grep, help, history, hostname, isatty, kill, la, ll, ls, man, nextd, open, popd, prevd, prompt_hostname, prompt_pwd, psub, pushd, realpath, seq, setenv, suspend, trap, type, umask, up-or-search, vared, wait

می‌توانید متن سورس هر تابع را با ارسال نام آن به دستور functions مشاهده نمایید:

> functions ls
function ls --description 'List contents of directory'
    command ls -G $argv
end

برای اطلاعات بیشتر، به بخش توابع مراجعه کنید <#syntax-function>.

[2]
البته تابعی به نام alias <> وجود دارد، اما صرفاً میانبری برای ساخت توابع است. فیش همچنین مخفف‌ها را از طریق دستور abbr <> ارائه می‌دهد <#abbreviations>.

حلقه‌های While:

while true
    echo "Loop forever"
end
# Prints:
# Loop forever
# Loop forever
# Loop forever
# بله، این واقعاً تا ابد تکرار خواهد شد، مگر اینکه با ctrl-c آن را متوقف کنید.

حلقه‌های For برای پیمایش روی یک لیست به کار می‌روند؛ برای مثال لیستی از فایل‌ها:

for file in *.txt
    cp $file $file.bak
end

برای پیمایش روی بازه‌ای از اعداد می‌توان از دستور seq استفاده کرد:

for x in (seq 5)
    touch file_$x.txt
end

برای اطلاعات بیشتر، به بخش حلقه‌ها و بلوک‌ها مراجعه کنید <#syntax-loops-and-blocks>.

برخلاف سایر پوسته‌ها، در فیش متغیری مانند PS1 برای خط اعلان وجود ندارد. برای نمایش اعلان، فیش تابع fish_prompt <> را اجرا کرده و خروجی آن را به عنوان اعلان نشان می‌دهد. و در صورت وجود، تابع fish_right_prompt <> را نیز برای نمایش اعلان سمت راست اجرا می‌کند.

می‌توانید اعلان اختصاصی خود را مستقیماً از خط فرمان تعریف کنید:

> function fish_prompt; echo "New Prompt % "; end
New Prompt % _

سپس اگر از آن راضی بودید، می‌توانید با تایپ دستور funcsave fish_prompt آن را روی دیسک ذخیره کنید. این کار اعلان را در مسیر ~/.config/fish/functions/fish_prompt.fish ذخیره می‌کند (یا اگر مایل باشید می‌توانید از ابتدا آن فایل را به صورت دستی بسازید).

استفاده از اعلان‌های چندخطی کاملاً مجاز است. رنگ‌ها را می‌توان از طریق set_color <> با ارسال نام رنگ‌های ANSI یا کدهای هگزادسیمال RGB تعیین کرد:

function fish_prompt
    set_color purple
    date "+%m/%d/%y"
    set_color FF0000
    echo (pwd) '>' (set_color --reset)
end

این خط اعلان به این صورت نمایش داده خواهد شد:

02/06/13
/home/tutorial > _

همچنین ببینید: نوشتن خط اعلان اختصاصی <>.

می‌توانید با اجرای دستور fish_config در یک رابط وب، یا با fish_config prompt برای نسخه‌ای ساده‌تر درون ترمینال، از میان اعلان‌های نمونه یکی را برگزینید.

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

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

برای اضافه کردن مسیرهای /usr/local/bin و /usr/sbin به ابتدای $PATH، می‌توانید بنویسید:

> set PATH /usr/local/bin /usr/sbin $PATH

برای حذف /usr/local/bin از $PATH، می‌توانید بنویسید:

> set PATH (string match -v /usr/local/bin $PATH)

برای سازگاری با سایر پوسته‌ها و دستورات خارجی، $PATH یک متغیر مسیر <#variables-path> است و به همین دلیل هنگام قرار گرفتن داخل کوتیشن، با دونقطه (نه فاصله) متصل می‌شود:

> echo "$PATH"
/usr/local/sbin:/usr/local/bin:/usr/bin

و به همین ترتیب نیز صادر می‌شود؛ همچنین هنگامی که فیش شروع به کار می‌کند، متغیر $PATH دریافتی را بر اساس دونقطه به یک لیست تبدیل می‌کند.

می‌توانید این تغییرات را مستقیماً در فایل config.fish انجام دهید؛ همان‌طور که ممکن است در سایر پوسته‌ها با فایل .profile انجام دهید.

یک روش سریع‌تر، استفاده از تابع fish_add_path <> است که در صورت عدم وجود دایرکتوری‌های داده‌شده در مسیر، آن‌ها را به PATH اضافه می‌کند. این تابع این کار را از طریق ویرایش متغیر یونیورسال $fish_user_paths انجام می‌دهد که به طور خودکار به ابتدای $PATH اضافه می‌گردد. برای مثال جهت اضافه کردن همیشگی /usr/local/bin به $PATH خود، می‌توانید بنویسید:

> fish_add_path /usr/local/bin

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

همچنین می‌توانید متغیر $fish_user_paths را مستقیماً ویرایش کنید، اما باید مراقب باشید که در فایل config.fish به صورت بدون قید و شرط مقداری به آن اضافه نکنید، زیرا با هر بار باز شدن پوسته طولانی‌تر خواهد شد.

فیش کار خود را با اجرای دستورات موجود در فایل ~/.config/fish/config.fish آغاز می‌کند. در صورت عدم وجود، می‌توانید آن را ایجاد کنید.

می‌توان توابع و متغیرها را مستقیماً در فایل config.fish با استفاده از دستوراتی که در بالا ذکر شد تعریف کرد؛ برای مثال:

> cat ~/.config/fish/config.fish
set -x PATH $PATH /sbin/
function ll
    ls -lh $argv
end

با این حال، روش رایج‌تر و بسیار کارآمدتر، استفاده از توابع بارگذاری خودکار (Autoloading Functions) و متغیرهای یونیورسال است.

اگر می‌خواهید پیکربندی خود را سازمان‌دهی کنید، فیش همچنین دستورات موجود در فایل‌های .fish در مسیر ~/.config/fish/conf.d/ را می‌خواند. برای جزئیات به فایل‌های پیکربندی مراجعه کنید <#configuration>.

هنگامی که فیش با یک دستور مواجه می‌شود، تلاش می‌کند با جستجو برای فایلی هم‌نام با آن دستور در مسیر ~/.config/fish/functions/، تابعی را برای آن به طور خودکار بارگذاری کند.

برای مثال اگر می‌خواهید تابعی به نام ll داشته باشید، کافی است یک فایل متنی با نام ll.fish به دایرکتوری ~/.config/fish/functions اضافه کنید:

> cat ~/.config/fish/functions/ll.fish
function ll
    ls -lh $argv
end

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

> cat ~/.config/fish/functions/fish_prompt.fish
function fish_prompt
    echo (pwd) "> "
end

برای آشنایی با روش‌های ایجاد خودکار این فایل‌ها به مستندات funced <> و funcsave <>، و برای کنترل مسیر ذخیره آن‌ها به $fish_function_path <#syntax-function-autoloading> مراجعه کنید.

متغیر یونیورسال متغیری است که مقدار آن در تمام نمونه‌ها و پنجره‌های فیش، هم‌اکنون و در آینده - حتی پس از راه‌اندازی مجدد سیستم (Reboot) - به اشتراک گذاشته می‌شود. می‌توانید با دستور set -U یک متغیر را یونیورسال کنید:

> set -U EDITOR vim

اکنون در یک پوسته یا پنجره دیگر:

> echo $EDITOR
vim

شما تنها یک‌بار نیاز به تنظیم تعاملی متغیرهای یونیورسال دارید و هیچ نیازی به اضافه کردن آن‌ها به فایل‌های پیکربندی خود نیست <#configuration>. برای جزئیات بیشتر به بخش متغیرهای یونیورسال مراجعه نمایید <#variables-universal>.

اگر مایلید درباره فیش بیشتر بیاموزید، مستندات جامع و تفصیلی فراوانی وجود دارد <#intro>، کانال رسمی gitter به آدرس https://gitter.im/fish-shell/fish-shell، لیست پستی رسمی به آدرس https://lists.sourceforge.net/lists/listinfo/fish-users، و صفحه گیت‌هاب پروژه به آدرس https://github.com/fish-shell/fish-shell.

توسعه‌دهندگان fish-shell

توسعه‌دهندگان fish-shell

September 7, 2026 4.9