POSIX فرمان داخلی به نام command تعیین میکند، که میتواند برای این منظور به کار برود:
# POSIX if command -v qwerty >/dev/null; then echo qwerty exists else echo qwerty does not exist fi
در BASH، یک زوج دستور داخلی بیشتر نیز وجود دارد که ممکن است به کار بروند: hash و type. این هم مثالی با استفاده از hash:
# Bash if hash qwerty 2>/dev/null; then echo qwerty exists else echo qwerty does not exist fi
یا، اگر ترجیح میدهید type:
# Bash # .بدون در نظر گرفتن دستورات داخلی و غیره میکند PATH الزام به جستجوی type -P دستور if type -P qwerty >/dev/null; then echo qwerty exists else echo qwerty does not exist fi
پوسته Korn در عوض دارای whence میباشد:
# ksh if whence -p qwerty >/dev/null; then echo qwerty exists else echo qwerty does not exist fi
دستور داخلی command همچنین برای دستورات داخلی پوسته صحیح را باز میگرداند(برخلاف type -P). اگر شما باید به طور مطلق فقط PATH را بررسی کنید، تنها روش POSIX انجام تکرار روی آن است:
# POSIX IsInPath () ( [ $# -eq 1 ] && [ "$1" ] || return 2 set -f; IFS=: for dir in $PATH; do [ -z "$dir" ] && dir=. # رفتار موروثی [ -x "$dir/$1" ] && return done return 1 ) if IsInPath qwerty; then echo qwerty exists else echo qwerty does not exist fi
توجه نمایید که تابع تعریف شده فوق به جای ابروهای معمول، از پرانتزها در اطراف بدنه استفاده میکند. این باعث میشود بدنه در یک پوسته فرعی اجرا گردد، و این به دلیل آنست که ما میخواهیم نیازی به خنثی نمودن set -f یا IFS نداشته باشیم.
رویکرد تکرار کننده در اسکریپتهای configure نیز استفاده میشود. این هم نگارش ساده شدهای از یک چنین تستی:
# Bourne save_IFS=$IFS IFS=: found=no for dir in $PATH; do if test -x "$dir/qwerty"; then echo "qwerty is installed (in $dir)" found=yes break fi done IFS=$save_IFS if test $found = no; then echo "qwerty is not installed" fi
اسکریپتهای واقعی configure معمولاً خیلی بیشتر از این پیچیده هستند، چون آنان ممکن است با سیستمهایی سر و کار داشته باشند که در آنها $PATH به وسیله کاراکترهای کولن جدا نمیشوند، یا سیستمهایی که در آنها شاید برنامههای اجرایی پسوندهای انتخابی مانند .EXE دارند، یا متغیرهای $PATH که دایرکتوری کاری جاری به عنوان یک رشته تهی در آنها گنجانده شدهاند و غیره. اگر به چنین مطالبی علاقمند هستید، پیشنهاد میکنم یک اسکریپت configure واقعی تولید شده با autoconf گنو را بخوانید. آنها بیش از آن بلند و پیچیده میباشند که در این پرسش و پاسخ قرار داده شوند.
فرمان which (که غالباً یک اسکریپت csh است، اگر چه گاهی نیز به صورت باینری کامپایل شده است) برای این منظور قابل اطمینان نیست. which نمیتواند یک کد خروج سودمند تنظیم کند، و حتی نمیتواند خطاها را در stderr بنویسد. بنابر این، برای مطلع شدن از اجرای موفقیت آمیز آن، باید خروجیاش تفکیک بشود(هر جا که خروجی نوشته بشود).
# Bourne. Last resort -- using which(1) tmpval=`LC_ALL=C which qwerty 2>&1` if test $? -ne 0; then # این ماشین یک کد خروج غیرصفر which(1) در حال حاضر فرض خواهیم نمود که اگر # تنظیم کند، به راستی ناموفق بوده. هنوز باید حالتی را ببینیم که در آن # درست مثل موفقیت غلط -- یک عدم موفقیت غلط تنظیم میکند which(1) echo "qwerty is not installed. Please install it." else # صفر را بازگردانده، که به معنی موفقیت آن نیست. جستجو برای رشته های خطا case "$tmpval" in *no\ *\ in\ *|*not\ found*|'') echo "qwerty is not installed. Please install it." ;; *) echo "Congratulations -- it seems you have qwerty (in $tmpval)." ;; esac fi
توجه نمایید که خروجی which(1) موقعی که دستوری را پیدا نمیکند در تمام سکوها یکسان نیست. برای مثال، در HP-UX 10.20، این پیغام خطا را چاپ میکند no qwerty in /path /path /path ...، در OpenBSD 4.1، این پیغام خطا را qwerty: Command not found.، در دبیان (حداقل 3.1 تا 5.0) و SuSE، ابداً چیزی چاپ نمیکند، در Red Hat 5.2، چاپ میکند which: no qwerty in (/path:/path:...)، در Red Hat 6.2، همان پیغام را مینویسد، اما به جای خروجی استاندارد در خطای استاندارد، و در Gentoo، چیزی در stderr مینویسد.
ما قویاً پیشنهاد میکنیم از which استفاده نکنید. به جای آن یکی از دستورات داخلی یا رویکردهای تکرار را به کار ببرید.
پرسش و پاسخ 81 (آخرین ویرایش 2012-03-14 11:57:13 توسط pgas)