| FISH-FAQ(1) | fish-shell | FISH-FAQ(1) |
نام (NAME)
fish-faq - پرسشهای متداول درباره پوسته fish
توضیحات (DESCRIPTION)
این سند شامل پرسشها و پاسخهای متداول (FAQ) درباره نحوه کارکرد، ویژگیها، تفاوتهای رفتاری با سایر پوستهها و تنظیمات پوسته fish است.
معادل این ویژگی در بش (یا سایر پوستهها) چیست؟ (WHAT IS THE EQUIVALENT TO THIS THING FROM BASH (OR OTHER SHELLS)?)
صفحه راهنمای fish-for-bash-users(1) <> را مشاهده کنید.
چگونه یک متغیر محیطی را مقداردهی یا پاک کنم؟ (HOW DO I SET OR CLEAR AN ENVIRONMENT VARIABLE?)
از دستور set <> استفاده کنید:
set -x key value # typically set -gx key value set -e key
از نسخه 3.1 فیش به بعد، میتوانید مشابه سایر پوستهها با استفاده از نحو key=value some command یک متغیر محیطی را صرفاً برای اجرای یک دستور تنظیم کنید. دو خط زیر رفتاری یکسان دارند - بر خلاف سایر پوستهها، فیش در هر دو حالت مقدار value را چاپ میکند:
key=value echo $key begin; set -lx key value; echo $key; end
توجه داشته باشید که "صادرشده (exported)" یک حوزه (scope) متغیر <#variables-scope> نیست، بلکه یک وضعیت اضافی برای آن است. یک متغیر میتواند سراسری و صادرشده، محلی و صادرشده، یا حتی جهانشمول و صادرشده باشد. معمولاً منطقی است که یک متغیر صادرشده را به صورت سراسری (global) تعریف کنید.
چگونه بررسی کنم که آیا یک متغیر تعریف شده است؟ (HOW DO I CHECK WHETHER A VARIABLE IS DEFINED?)
از set -q var استفاده کنید. برای نمونه، if set -q var; echo variable defined; end. برای بررسی چند متغیر میتوانید از ترکیب با and و or به شکل زیر استفاده کنید:
if set -q var1; or set -q var2
echo either variable defined
end
به یاد داشته باشید که یک متغیر تعریفشده ممکن است خالی نیز باشد؛ چه از طریق نداشتن هیچ عنصری (اگر با set var مقداردهی شده باشد) یا تنها با داشتن عناصر خالی (اگر با set var "" مقداردهی شده باشد). برای نحوه برخورد با این حالتها ادامه مطلب را بخوانید.
چگونه بررسی کنم که آیا یک متغیر خالی نیست؟ (HOW DO I CHECK WHETHER A VARIABLE IS NOT EMPTY?)
از string length -q -- $var استفاده کنید. برای نمونه، if string length -q -- $var; echo not empty; end. توجه داشته باشید که string length فهرستی از چندین متغیر را به صورت فصل منطقی (یا / or) تفسیر میکند:
if string length -q -- $var1 $var2 $var3
echo at least one of these variables is not empty
end
به عنوان روشی جایگزین، از test -n "$var" استفاده کنید، اما به یاد داشته باشید که متغیر باید داخل نقلقول دوتایی (دابلکوتیشن) قرار گیرد. برای نمونه، if test -n "$var"; echo not empty; end. دستور test عملگرهای «و» (-a) و «یا» (-o) مخصوص خود را ارائه میدهد:
if test -n "$var1" -o -n "$var2" -o -n "$var3"
echo at least one of these variables is not empty
end
اگر میخواهید بدانید که آیا یک متغیر هیچ عنصری ندارد، از set -q var[1] استفاده کنید.
چرا به نظر میرسد دستور set -Ux (متغیرهای جهانشمول صادرشده) کار نمیکند؟ (WHY DOESN'T SET -UX (EXPORTED UNIVERSAL VARIABLES) SEEM TO WORK?)
یک متغیر سراسری (global) با همین نام از قبل وجود دارد.
متغیرهای محیطی نظیر EDITOR یا TZ را میتوان با استفاده از set -Ux به صورت جهانشمول (universal) تنظیم کرد. با این حال، اگر پیش از آغاز به کار فیش متغیر محیطی از قبل مقداردهی شده باشد (مثلاً توسط اسکریپتهای ورود به سیستم یا مدیران سیستم)، آن متغیر به عنوان یک متغیر سراسری وارد فیش میشود. حوزههای متغیرها <#variables-scope> از «داخل به خارج» جستجو میشوند، بدین معنا که ابتدا متغیرهای محلی، سپس متغیرهای سراسری و در نهایت متغیرهای جهانشمول بررسی میگردند.
این بدان معناست که مقدار سراسری بر مقدار جهانشمول اولویت و تقدم دارد.
برای پیشگیری از این مشکل، میتوانید تنظیمی را که فیش به ارث میبرد تغییر دهید. اگر این کار امکانپذیر نیست، دستوری را به فایل پیکربندی خود <#configuration> (معمولاً ~/.config/fish/config.fish) بیفزایید:
set -gx EDITOR vim
چگونه در هر بار ورود دستوری را اجرا کنم؟ معادل bashrc. یا profile. در فیش چیست؟ (HOW DO I RUN A COMMAND EVERY LOGIN? WHAT'S FISH'S EQUIVALENT TO .BASHRC OR .PROFILE?)
فایل ~/.config/fish/config.fish [1] را ویرایش کنید؛ در صورتی که وجود ندارد آن را بسازید (به نقطه ابتدای نام فایل توجه داشته باشید).
بر خلاف bashrc. و profile.، این فایل همواره خوانده میشود؛ حتی در پوستههای غیرتعاملی یا هنگام ورود به سیستم.
برای اجرای یک دستور صرفاً در پوستههای تعاملی، دستور status is-interactive را به این شکل بررسی کنید:
if status is-interactive
# use the coolbeans theme
fish_config theme choose coolbeans
end
- [1]
- بخش "~/.config" در این مسیر میتواند از طریق متغیر $XDG_CONFIG_HOME تنظیم شود؛ این مسیر صرفاً مقدار پیشفرض است.
چگونه اعلان خط فرمان (پرامپت) خود را تنظیم کنم؟ (HOW DO I SET MY PROMPT?)
اعلان خط فرمان خروجی تابع fish_prompt است. آن را در مسیر ~/.config/fish/functions/fish_prompt.fish قرار دهید. برای نمونه، یک اعلان ساده به شکل زیر است:
function fish_prompt
set_color $fish_color_cwd
echo -n (prompt_pwd)
set_color --reset
echo -n ' > '
end
همچنین میتوانید از ابزار پیکربندی تحت وب، fish_config <>، برای پیشنمایش و انتخاب از میان گالری اعلانهای نمونه استفاده کنید.
یا اینکه میتوانید از دستور fish_config در خط فرمان بهره ببرید:
> fish_config prompt show # displays all the prompts fish ships with > fish_config prompt choose disco # loads the disco prompt in the current shell > fish_config prompt save # makes the change permanent
چنانچه مایل به ویرایش اعلان موجود خود هستید، میتوانید از funced <> و funcsave <> استفاده کنید:
>_ funced fish_prompt # This opens up your editor (set in $EDITOR). # Modify the function, # save the file and repeat to your liking. # Once you are happy with it: >_ funcsave fish_prompt
این موضوع در مورد fish_right_prompt <> و fish_mode_prompt <> نیز صدق میکند.
چرا اعلان خط فرمان من [I] را نشان میدهد؟ (WHY DOES MY PROMPT SHOW A [I]?)
این مورد همان fish_mode_prompt <> است. هنگامی که با دستور fish_vi_key_bindings حالت vi را فعال کرده باشید، این نشانگر به صورت پیشفرض نمایش داده میشود.
اگر حالت vi را عمداً فعال نکردهاید، ممکن است یک تم یا افزونه متفرقه نصب کرده باشید که این کار را انجام میدهد.
اگر میخواهید این نمایش را تغییر دهید یا غیرفعال کنید، تابع fish_mode_prompt را مثلاً با استفاده از funced <> ویرایش کنید.
چگونه رنگهای برجستهسازی نحو را سفارشیسازی کنم؟ (HOW DO I CUSTOMIZE MY SYNTAX HIGHLIGHTING COLORS?)
از ابزار پیکربندی تحت وب که توسط fish_config <> راهاندازی میشود استفاده کنید، یا مجموعه متغیرهای محیطی fish_color <#variables-color> را تغییر دهید، یا از زیردستور fish_config theme <> به این شکل بهره ببرید:
> fish_config theme show # to demonstrate all the colorschemes > fish_config theme choose coolbeans # to load the "coolbeans" theme
چگونه پیام خوشآمدگویی را تغییر دهم؟ (HOW DO I CHANGE THE GREETING MESSAGE?)
مقدار متغیر fish_greeting را تغییر دهید یا یک تابع fish_greeting <> ایجاد کنید. برای نمونه، جهت حذف پیام خوشآمدگویی از دستور زیر استفاده کنید:
set -U fish_greeting
یا چنانچه ترجیح میدهید از متغیر جهانشمول استفاده نکنید، دستور زیر را به کار ببرید:
set -g fish_greeting
در فایل config.fish <#configuration>.
چگونه دستوری را از تاریخچه اجرا کنم؟ (HOW DO I RUN A COMMAND FROM HISTORY?)
بخشی از دستور را تایپ کرده و سپس کلیدهای پیکان بالا (↑) یا پایین (↓) را بفشارید تا میان تطابقهای تاریخچه پیمایش کنید، یا کلیدهای ctrl-r را بزنید تا تاریخچه در یک صفحهبندیکننده (pager) قابل جستجو باز شود. در این صفحهبندیکننده میتوانید به ترتیب با زدن ctrl-r یا ctrl-s میان تاریخچههای قدیمیتر یا جدیدتر حرکت کنید.
کلیدهای میانبر پیشفرض دیگر شامل ctrl-p (بالا) و ctrl-n (پایین) هستند. برای اطلاعات بیشتر بخش تاریخچه دستورات قابل جستجو <#history-search> را مشاهده کنید.
چرا جایگزینی تاریخچه (مانند
زیرا جایگزینی تاریخچه یک رابط کاربری نامناسب است که پیش از امکانپذیر شدن ویرایش تعاملی خط فرمان اختراع شده بود. فیش به جای افزودن این شبهنحو، امکانات جستجو و بازیابی عالی در تاریخچه را برگزیده است. مهاجرت به این سبک نیازمند تغییری کوچک در عادتها است: اگر میخواهید خط یا واژهای قدیمی را اصلاح کنید، ابتدا آن را فراخوانی کرده و سپس ویرایش کنید.
به عنوان یک حالت ویژه، در بیشتر مواقع جایگزینی تاریخچه به صورت sudo !! به کار میرود. در این شرایط کلیدهای alt-s را بفشارید تا آخرین خط فرمان شما با پیشوند sudo فراخوانی شود (یا در صورت وجود هر متنی در خط فرمان فعلی، پیشوند sudo را روی آن فعال یا غیرفعال کند).
به طور کلی، بازیابی تاریخچه در فیش به این شکل عمل میکند:
- مشابه سایر پوستهها، کلید پیکان بالا (up) خطوط کامل را از آخرین خط اجراشده فراخوانی میکند؛ بنابراین به جای تایپ !!، کافی است کلید پیکان بالا را فشار دهید.
- اگر خط موردنظر شما مربوط به گذشتههای دورتر در تاریخچه است، بخشی از آن خط را تایپ کرده و سپس یک یا چند بار کلید پیکان بالا را بزنید. با این کار خطوط فراخوانیشده بر اساس این متن فیلتر میشوند و بسیار سریعتر به خط موردنظرتان میرسید. این سازوکار جایگزین دستوراتی چون "!vi"، "!?bar.c" و مانند آن است. در صورتی که تمایل دارید زمینه و بافت بیشتری را مشاهده کنید، میتوانید ctrl-r را بزنید تا تاریخچه در صفحهبندیکننده باز شود.
- کلید alt-up آرگومانها را به صورت تکی از آخرین آرگومان در آخرین خط اجراشده فراخوانی میکند. این قابلیت میتواند به جای "!$" به کار رود.
برای جزئیات بیشتر درباره ویرایش خط در فیش، مستندات ویرایشگر <#editor> را ببینید.
با این وجود، میتوانید با استفاده از کوتاهنوشتها (Abbreviations) <#abbreviations> جایگزینی تاریخچه را پیادهسازی کنید. در اینجا فقط برای !! آورده شده است:
function last_history_item; echo $history[1]; end abbr -a !! --position anywhere --function last_history_item
این دستور را اجرا کنید تا در هر کجای خط فرمان، !! با آخرین مدخل تاریخچه جایگزین شود. برای ماندگار شدن، آن را در config.fish <#configuration> قرار دهید.
چگونه یک زیردستور را اجرا کنم؟ بکتیک کار نمیکند! (HOW DO I RUN A SUBCOMMAND? THE BACKTICK DOESN'T WORK!)
پوسته fish برای زیردستورها از پرانتز استفاده میکند. برای نمونه:
for i in (ls)
echo $i
end
همچنین فیش از نحو آشنای $() حتی درون نقلقولها نیز پشتیبانی میکند. کاراکتر بکتیک (backtick) پشتیبانی نمیشود زیرا استفاده از آن حتی در پوستههای POSIX نیز منع شده است؛ این نویسهها قابلیت تودرتویی ضعیفی دارند و تمایز آنها از نقلقول تکی ('') دشوار است.
خروجی دستور من (مانند pkg-config) به صورت یک رشته متنی بلند ظاهر میشود؟ (MY COMMAND (PKG-CONFIG) GIVES ITS OUTPUT AS A SINGLE LONG STRING?)
بر خلاف سایر پوستهها، فیش خروجی جایگزینی دستورات را تنها بر اساس خطوط جدید (newline) تفکیک میکند، نه بر مبنای فاصلهها، تبها یا نویسههای موجود در $IFS.
این بدان معناست که اگر دستور زیر را اجرا کنید:
count (printf '%s ' a b c)
مقدار 1 چاپ خواهد شد، زیرا عبارت "a b c " به صورت یکپارچه به کار گرفته شده است. اما اگر بنویسید:
count (printf '%s\n' a b c)
مقدار 3 چاپ میشود، چرا که آرگومانهای "a"، "b" و "c" را به صورت جداگانه به دستور count داده است.
در بیشتر مواقع، تفکیک بر پایه فاصلهها ناخواسته است، بنابراین این رفتار یک بهبود به شمار میرود؛ در واقع به همین دلیل است که معمولاً درباره مشکلات نام فایلهای حاوی فاصله میشنوید.
با این حال گاهی اوقات، به ویژه با ابزارهایی مانند pkg-config و برنامههای مرتبط، تفکیک بر پایه فاصله مورد نیاز است.
در این حالتها از string split -n " " به شکل زیر استفاده کنید:
g++ example_01.cpp (pkg-config --cflags --libs gtk+-2.0 | string split -n " ")
گزینه -n باعث میشود عناصر خالی حذف شوند، مشابه رفتاری که پوستههای POSIX انجام میدهند.
چگونه وضعیت خروج (Exit Status) یک دستور را به دست آورم؟ (HOW DO I GET THE EXIT STATUS OF A COMMAND?)
از متغیر $status استفاده کنید. این متغیر جایگزین متغیر $? در سایر پوستهها است.
somecommand
if test $status -eq 7
echo "That's my lucky number!"
end
اگر فقط بررسی موفقیت یا عدم موفقیت دستور برایتان مهم است، میتوانید دستور را مستقیماً به عنوان شرط دستور if اجرا کنید:
if somecommand
echo "Command succeeded"
else
echo "Command failed"
end
یا چنانچه میخواهید در صورت موفقیت یا شکست دستور اول، دستور دیگری اجرا شود، از and یا or استفاده کنید:
somecommand or someothercommand
برای اطلاعات بیشتر، بخش شرایط <#syntax-conditional> و مستندات test <> و if <> را مشاهده کنید.
دستور من خطای
به طور خلاصه: نویسه عام (wildcard) را نقلقول <#quotes> یا گریزدهی (escape) <#escapes> کنید:
scp user@ip:/dir/"string-*"
هنگامی که فیش علامت ستاره * بدون نقلقول را میبیند، بسط نویسه عام <#expand-wildcard> را انجام میدهد. این بدان معناست که تلاش میکند نام فایلها را با رشته دادهشده تطبیق دهد.
اگر نویسه عام با هیچ فایلی تطابق نداشته باشد، فیش به جای اجرای دستور یک پیام خطا چاپ میکند:
> echo *this*does*not*exist
fish: No matches for wildcard '*this*does*not*exist'. See `help expand`.
echo *this*does*not*exist
^
حال، پوسته bash نیز در چنین وضعیتی تلاش میکند فایلها را تطبیق دهد، اما هنگامی که تطابقی پیدا نمیکند، رشته واقعی نویسه عام را بدون تغییر ارسال مینماید.
این بدان معناست که دستوراتی مانند مثال فوق:
scp user@ip:/dir/string-*
یا
apt install postgres-*
به نظر میرسد که به درستی کار میکنند، زیرا بیشتر اوقات رشته تطابقی پیدا نمیکند و در نتیجه عبارت string-* ارسال میشود که توسط برنامه مقصد تفسیر میگردد.
اما این موضوع همچنین به این معنی است که هر لحظه با ایجاد یک فایل مطابق یا اجرای دستور در یک پوشه کاری متفاوت، ممکن است این دستورات از کار بیفتند؛ و برای مقابله با این مشکل bash به راهکارهای دورزدن نظیر این نیاز دارد:
for f in ./*.mpg; do
# We need to test if the file really exists because
# the wildcard might have failed to match.
test -f "$f" || continue
mympgviewer "$f"
done
(برگرفته از http://mywiki.wooledge.org/BashFAQ/004)
به همین دلایل، فیش چنین رفتاری ندارد و در عوض انتظار دارد ستارهها در صورتی که قرار نیست بسط داده شوند، داخل نقلقول یا گریزدهی قرار گیرند.
این رفتار مشابه گزینه "failglob" در پوسته bash است.
چرا هنگامی که فیش پوسته ورود من است اتصالات SSH/SCP/RSYNC دچار مشکل میشوند؟ (WHY WON'T SSH/SCP/RSYNC CONNECT PROPERLY WHEN FISH IS MY LOGIN SHELL?)
این مشکل ممکن است با پیامهایی نظیر "Received message too long"، "open terminal failed: not a terminal"، "Bad packet length"، یا "Connection refused" همراه با خروجیهای عجیب در پیامهای ssh_exchange_identification در گزارش اشکالزدایی نمایان شود.
این اتفاق معمولاً به این دلیل رخ میدهد که فیش فایل پیکربندی کاربر <#configuration> (~/.config/fish/config.fish) را همواره میخواند؛ چه پوسته تعاملی باشد، چه پوسته ورود، چه غیرتعاملی و چه غیرورود.
این رفتار کارها را سادهتر میکند، اما همچنین بدین معناست که اگر config.fish خروجی متنی تولید کند، این خروجی حتی در پوستههای غیرتعاملی نظیر پوستهای که ابزارهای ssh/scp/rsync هنگام اتصال اجرا میکنند نیز تولید خواهد شد.
هر کدی در config.fish که خروجی تولید میکند باید با بررسی شرط status is-interactive (یا در صورت تمایل status is-login) محافظت شود:
if status is-interactive ... end
همین موضوع برای نمونه هنگامی صادق است که tmux را بدون محافظ در config.fish اجرا کنید، که باعث ایجاد پیامی مانند sessions should be nested with care, unset $TMUX to force میگردد.
با اشکالات گرافیکی عجیب (اثر پلکانی، نویسههای شبح، مکاننمای نابجا و...) مواجه میشوم؟ (I'M GETTING WEIRD GRAPHICAL GLITCHES (A STAIRCASE EFFECT, GHOST CHARACTERS, CURSOR IN THE WRONG POSITION,...)?)
در یک ترمینال، برنامه در حال اجرا و خود ترمینال باید بر سر پهنای نویسهها توافق داشته باشند تا حرکت مکاننما به درستی مدیریت شود.
این امر برای فیش بیش از سایر پوستهها اهمیت دارد، زیرا قابلیتهایی چون برجستهسازی نحو و پیشنهادهای خودکار با جابجایی مکاننما پیادهسازی شدهاند.
گاهی اوقات بر سر پهنای نویسهها ناهماهنگی پیش میآید. این موضوع علل و راهحلهای متعددی دارد:
- ممکن است نویسه موردنظر برای سیستم شما بیش از حد جدید باشد و سیستم آن را نشناسد - در این حالت باید از بهکارگیری آن نویسه خودداری کنید.
- ممکن است فیش یا ترمینال شما نویسه را نشناسند یا با آن اشتباه برخورد کنند - در این حالت باید فیش یا ترمینال اصلاح شود یا نسخه بهروزرسانیشده آن را نصب کنید.
- نویسه دارای پهنای «مبهم» (ambiguous) است و فیش پهنای آن را برابر X در نظر میگیرد در حالی که ترمینال آن را Y میداند. در این حالت یا باید پیکربندی ترمینال را تغییر دهید یا متغیر $fish_ambiguous_width را روی مقدار صحیح تنظیم کنید.
- نویسه یک ایموجی (emoji) است و سیستم شما تنها از یونیکد ۸ پشتیبانی میکند. در این حالت متغیر $fish_emoji_width را برابر 1 قرار دهید.
این امر همچنین بدین معناست که چند مورد قابل پشتیبانی نیستند:
- قلمهای با پهنای نامساوی (غیر تکفاصله یا Non-monospace) - هیچ راهی برای فیش وجود ندارد تا پهنای یک نویسه خاص را تشخیص دهد، زیرا فیش تأثیری بر رندرینگ قلم ترمینال ندارد.
- پهناهای متفاوت برای چندین نویسه با پهنای مبهم - هیچ راهی وجود ندارد که فیش بفهمد شما چه پهنایی را به هر یک از این نویسهها اختصاص دادهاید.
فیش در یک ترمینال خاص کار نمیکند (FISH DOES NOT WORK IN A SPECIFIC TERMINAL)
ممکن است ترمینال تمام پیشنیازهای فیش <> را برآورده نکند. لطفاً این مشکل را در سامانه پیگیری اشکالات ترمینال خود و فیش گزارش دهید.
حذف نصب فیش (UNINSTALLING FISH)
چنانچه میخواهید فیش را حذف نصب کنید، ابتدا اطمینان حاصل نمایید که فیش به عنوان پوسته پیشفرض شما تنظیم نشده باشد. اگر مطمئن نیستید، دستور chsh -s /bin/bash را اجرا کنید.
اگر فیش را با یک مدیر بسته نصب کردهاید، از دستور حذف همان مدیر بسته استفاده کنید. اگر فیش را خودتان کامپایل و نصب کردهاید، با فرض اینکه آن را در مسیر usr/local/ نصب کرده باشید، دستورات زیر را اجرا کنید:
rm -Rf /usr/local/etc/fish /usr/local/share/fish ~/.config/fish rm /usr/local/share/man/man1/fish*.1 cd /usr/local/bin rm -f fish fish_indent
نویسنده (AUTHOR)
توسعهدهندگان پوسته fish
حق نشر (COPYRIGHT)
توسعهدهندگان پوسته fish
| September 7, 2026 | 4.9 |