|| و &&
command1 && command2
این دستور command1 را اجرا میکند و اگر خروجی صفر بود (درست) command2 اجرا میشود
[ -f fileName ] && ./fileName
این قطعه کد (که خیلی استفاده میشه) یعنی اگر فایل fileName وجود داشت آنرا اجرا کن در غیر این صورت کاری انجام نمیدهد
* اگر بخواهیم چند کار انجام دهیم آنها رو با {} احاطه میکنیم
|| برعکس && هست یعنی اگر خروجی command1 غیر صفر بود command2 اجرا میشود
Redirecting
توی shell سه نوع ورودی/خروجی داریم:
۰ - ورودی از keyboard اسم:standard input
۱ - خروجی به console اسم:standard output
۳ - خروجی به console برای خطاها اسم: standard error
× برای توضیح بگم که stderr با stdout هیچ فرقی نداره و فقط برای جداسازی این دوتا هست
[n]> file
خروجی استاندارد یا شماره n را در file میریزد
[n]>> file
خروجی استاندارد یا شماره n را در انتهای file میریزد و آنرا پاک نمیکند
[n]< file
ورودی استاندارد یا شماره n را از file میخواند
[n]<> file
فایل file را برای ورودی و خروجی استاندارد یا n باز میکند
[n1]>&n2
خروجی استاندارد یا شماره n1 را به n2 میفرستد
[n1]<&n2
ورودی استاندارد یا شماره n1 را به n2 میفرستد
[n]<&-
ورودی استاندارد یا n را میبندد
[n]>&-
خروجی استاندارد یا n را میبندد
[n]<< endWord
write here
and here
endWord
هرچه بین دو تا endWord نوشته شده باشه رو به ورودی استاندارد یا n میفرستد
اگر میخواهید از دستور cmd هیچ خروجی روی تصویر نشان داده نشود:
cmd 2>&1 >/dev/null
* /dev/null مثل یک سطل آشغال هست هرچی توش بریزین به هیچ جایی نمیره
پایپ
فرض کنیم میخواهیم اسم فایلهای یک دیرکتوری را با ls بگیریم و با sort مرتب کنیم
ls > temp
sort < temp
به جای استفاده از فایل واسطه میتوانیم مستقیما از خروجی یک دستور خوانده و به ورودی دیگری بدیم با یه پایپ (لوله)!
ls | sort
توابع و پارامترها
توی shell توابع یک نوع برنامه هست و بلعکس!
برای همین همهی مطالب این قسمت (به جز تعریف تابع) برای یک script بدون تابع هم (که خودش یک برنامه است) برقرار است
تعریف تابع
FunctionName()
{
commands
.
.
.
return exitStatus
}
exitStatus یک عدد صحیح است که به هنوان خروجی در نظر گرفته میشود
صدازدن تابع
از اون جایی تابع همون برنامهس از همون syntax استفاده میکنیم
func param1 param2
و کد خروجی هم (از اونجایی که یه برنامه هست
) توی متغییر ?$ ذخیره میشه
برای کسانی که نمیدونن هم بگم هر برنامه یه کد خروجی داره که توی ? ذخیره میشه که معمولا نشان دهندهی اینه که برنامه درست اجرا شده یا نه:
arman:~$ ls /
bin cdrom etc initrd lib media opt root srv tmp var
boot dev home initrd.img lost+found mnt proc sbin sys usr vmlinuz
arman:~$ echo $?
0
arman:~$ ls /err
ls: /err: No such file or directory
arman:~$ echo $?
2
برای اینکه کد خروج کل shell script رو معین کنیم یا از کل برنامه خارج شویم از تابع exit استفاده میکنیم
مثلا
exit 2
پارامترها
پارامتر اول توی 1$، پارامتر دوم توی 2$، ... و پارامتر صفرم توی 0$ ذخیره میشه
test.sh:
#!/bin/sh
echo "0 = $0 1 = $1 2 = $2"
arman:~$ ./test.sh hello world
0 = ./test.sh 1 = hello 2 = world
پارامترهای خاص
پارامتر صفرم (0$) همون اسم برنامه هست (به همون طریقی که اجرا شده)
متغییر #$ تعداد پارامترها را مشخص میکنه
متغییر @$ شامل تمام متغییرها است که وقتی به string تبدیل میشود پارامترها را جداگانه مشخص میکند
متغییر *$ شامل تمام متغییرها است که وقتی به string تبدیل میشود پارامترها به هم میچسبند و بین آنها اولین کاراکتر متغییر IFS هست (که معمولا space هست)
متغییر $$ شماره پروسه shell جاری هست
متغییر !$ شماره پروسه آخرین دستور background یا آخرین پایپ است
ابن مثال خیلی واضح تر از بالاست
test.sh:
#!/bin/sh
echo "0 = $0"
echo "# = $#"
echo "@ = $@"
for a in "$@"; do
echo $a
done
IFS="/"
echo "* = $*"
for a in "$*"; do
echo $a
done
echo "\$ = $$"
arman:~$ ./test.sh "hello world" hello2 world2
0 = ./test.sh
# = 3
@ = hello world hello2 world2
hello world
hello2
world2
* = hello world/hello2/world2
hello world hello2 world2
$ = 19750