IlmHamroh
JavaScript Full-stack/1-qism. Kompyuter, fayllar va terminal28/40-dars18 daqiqa
Mundarija (35)

Shell skript yozish asoslari: bash'da birinchi avtomatlashtirish

Qisqacha: Shell skript — terminal buyruqlari ketma-ket yozilgan matnli fayl (odatda .sh). Birinchi qatori — shebang #!/usr/bin/env bash: "meni bash bajarsin". Ishga tushirish: bash skript.sh yoki chmod +x skript.sh dan keyin ./skript.sh. Ichida o'zgaruvchilar, $1 (birinchi argument), if, for ishlatiladi. set -e skriptni birinchi xatoda to'xtatadi.

Bu darsda

  • Birinchi skriptingizni yozib, uni ikki usulda ishga tushirasiz.
  • Shebang qatori va chmod +x nima uchun kerakligini tushuntira olasiz.
  • Skriptga tashqaridan qiymat berasiz: $1, $2, $#, $@.
  • Qo'shtirnoq qoidalarini bilasiz: "..." ichida o'zgaruvchi ochiladi, '...' ichida — yo'q.
  • if bilan tekshirasiz, for bilan takrorlaysiz, set -euo pipefail bilan skriptni xavfsiz qilasiz.

Oldin bilishingiz kerak: Exit code va buyruqlarni zanjirlash, Muhit o'zgaruvchilari va PATH, Fayl ruxsatlari va foydalanuvchilar.

1. Nega bu kerak?

Tasavvur qiling: har kuni ish oxirida sayt papkangizning zaxira nusxasini olasiz. Buning uchun uch buyruq yozasiz: zaxira papkasini yaratish, bugungi sanani aniqlash, nusxalash. Har kuni, qo'lda.

Bir kuni sanani adashtirasiz. Boshqa kuni cp dagi -r ni unutasiz. Bir haftadan keyin esa umuman unutib qo'yasiz.

Yechim — bu buyruqlarni bir marta faylga yozib qo'yish. Keyin bitta buyruq bilan hammasi bajariladi:

bash
./zaxira.sh sayt
text
Tayyor: zaxira/sayt-2026-09-27

Bunday fayl shell skript (shell script) deyiladi. Bu dars oxirida aynan shu zaxira.sh ni o'zingiz yozasiz.

O'xshatish: plov retsepti. Har safar oshpazdan "endi nima qilay?" deb so'ramaysiz — retsept daftarga yozilgan, qadamlari tartib bilan. Skript — kompyuter uchun yozilgan retsept.

2. Birinchi skript

2.1 Faylni yaratish

Git Bash, WSL yoki macOS terminalida mashq papkasini oching:

bash
mkdir -p skriptlar
cd skriptlar

Endi salom.sh faylini yarating. Uni VS Code'da (code salom.sh) yoki muhit o'zgaruvchilari darsidagi nano da (nano salom.sh) ochib, quyidagini yozing:

bash
#!/usr/bin/env bash
# Birinchi skriptim
echo "Assalomu alaykum!"
echo "Bugun: $(date +%d.%m.%Y)"
echo "Siz turgan papka: $(pwd)"

Qatorma-qator:

  1. #!/usr/bin/env bash — shebang. Uni sal pastda batafsil ko'ramiz.
  2. # Birinchi skriptim — izoh. # dan keyingi hamma narsani bash o'qimaydi. Izoh odamlar uchun: "bu skript nima qiladi".
  3. echo "Assalomu alaykum!" — tanish echo.
  4. $(date +%d.%m.%Y) — yangi narsa: buyruq natijasini o'rniga qo'yish. Bash avval qavs ichidagi date ni bajaradi va uning natijasini (27.09.2026) satrga qo'yadi. +%d.%m.%Y — date ga "kun.oy.yil ko'rinishida chiqar" degan buyruq.
  5. $(pwd) — xuddi shunday: joriy papka yo'li.

2.2 Ishga tushirish: bash salom.sh

Eng oddiy usul — bash dasturiga faylni berish:

bash
bash salom.sh
text
Assalomu alaykum!
Bugun: 27.09.2026
Siz turgan papka: /home/ali/skriptlar

Bash faylni ochdi va ichidagi buyruqlarni yuqoridan pastga, birma-bir bajardi — xuddi siz ularni terminalga qo'lda yozgandek.

2.3 Shebang va ./salom.sh

Har safar bash deb yozmasdan, skriptni oddiy dastur kabi ishga tushirish mumkin. Buning uchun ikki narsa kerak.

Birinchisi — shebang. Fayl boshidagi #! belgilari (inglizcha "sharp" + "bang" — # va ! belgilari nomlaridan) operatsion tizimga aytadi: "bu faylni qaysi dastur bajarsin". /usr/bin/env bash esa "PATH'dan bash ni topib, o'shanga ber" degani. Nega to'g'ridan-to'g'ri /bin/bash emas? Chunki turli tizimlarda bash turli joyda bo'ladi, env esa uni PATH bo'yicha o'zi topadi.

Ikkinchisi — bajarish huquqi. Fayl ruxsatlari darsida x (execute) huquqini ko'rgan edik. Yangi fayl odatda bu huquqsiz yaratiladi:

bash
chmod +x salom.sh
./salom.sh

Natija bash salom.sh dagidek.

Nega ./? PATH darsidan eslang: nomi bilan yozilgan buyruq faqat PATH papkalaridan qidiriladi. Joriy papka PATH'da yo'q — bu xavfsizlik uchun ataylab qilingan. ./ — "aynan shu papkadagi fayl" degan aniq yo'l.

bash
salom.sh
text
bash: salom.sh: command not found

./salom.sh yozganingizda nima bo'lishini bir rasmda ko'ramiz:

flowchart TD
  A["./salom.sh"] --> B{"Faylda x huquqi bormi?"}
  B -- "yo'q" --> X["Permission denied, kod 126"]
  B -- "ha" --> C["OS birinchi qatorni o'qiydi:<br/>#!/usr/bin/env bash"]
  C --> D["env PATH'dan bash'ni topadi"]
  D --> E["bash faylni qatorma-qator bajaradi"]

Maslahat: Git Bash'da (Windows'da) chmod +x ta'sir qilmaydi: Windows'da x huquqi yo'q, shuning uchun Git Bash #! bilan boshlangan faylni o'zi bajariladigan deb hisoblaydi. Linux, macOS va WSL'da esa chmod +x majburiy. Serverlar Linux'da — odatni hozirdan shakllantiring.

Tekshirib ko'ring: Linux'da yangi hisobot.sh yaratdingiz va darhol ./hisobot.sh yozdingiz. Nima bo'ladi va qanday tuzatasiz? Yana qaysi usul chmod siz ham ishlaydi?

Javob

bash: ./hisobot.sh: Permission denied xatosi (exit code 126). Faylda x huquqi yo'q. Tuzatish: chmod +x hisobot.sh. chmod siz ishlaydigan usul — bash hisobot.sh: bu holda fayl dastur sifatida emas, bash uchun matn sifatida o'qiladi va x huquqi kerak emas.

3. O'zgaruvchilar va argumentlar

3.1 Skript ichida o'zgaruvchi

O'zgaruvchilar muhit o'zgaruvchilari darsidagi qoidalar bilan ishlaydi: nom=qiymat (bo'sh joysiz), o'qish — $nom. Hisob-kitob uchun esa $(( ... )) ishlatiladi:

bash
#!/usr/bin/env bash
narx=12000
soni=3
jami=$((narx * soni))
echo "Jami: $jami so'm"
text
Jami: 36000 so'm

$(( )) ichida +, -, *, / ishlaydi va o'zgaruvchilarni $ siz yozsa ham bo'ladi. Faqat butun sonlar: $((7 / 2)) — 3, kasr qismi tashlanadi.

3.2 Tashqaridan qiymat: $1, $2

Skript har safar bir xil ish qilsa, uning foydasi kam. Unga tashqaridan qiymat berish uchun argumentlar ishlatiladi — buyruq anatomiyasi darsidagi argumentlarning o'zi. Skript ichida ular maxsus o'zgaruvchilarda turadi:

O'zgaruvchi Nima
$1, $2, ... 1-, 2-, ... argument
$# Argumentlar soni
$@ Barcha argumentlar
$0 Skriptning o'z nomi

mehmon.sh:

bash
#!/usr/bin/env bash
echo "Xush kelibsiz, $1!"
echo "Siz ${2}dan keldingiz."
echo "Argumentlar soni: $#"
bash
bash mehmon.sh Malika Samarqand
text
Xush kelibsiz, Malika!
Siz Samarqanddan keldingiz.
Argumentlar soni: 2

${2}dan — muhit o'zgaruvchilari darsidagi jingalak qavs: shundan keyin qo'shimcha yopishib keladi. $2dan desak ham bu yerda ishlardi (raqamli nom bitta raqamdan iborat), lekin ${...} odati adashishdan saqlaydi.

3.3 Bo'sh joyli argument

Argumentlar bo'sh joy bilan ajratiladi. Ism va familiyani bitta argument qilish uchun — qo'shtirnoq:

bash
bash mehmon.sh Ali Valiyev Toshkent
bash mehmon.sh "Ali Valiyev" Toshkent
text
Xush kelibsiz, Ali!
Siz Valiyevdan keldingiz.
Argumentlar soni: 3
Xush kelibsiz, Ali Valiyev!
Siz Toshkentdan keldingiz.
Argumentlar soni: 2

Birinchi holatda Valiyev ikkinchi argument bo'lib qoldi — "Valiyevdan keldingiz". Qo'shtirnoq uch so'zni ikkita argumentga aylantirdi.

Tekshirib ko'ring: bash mehmon.sh (argumentsiz) nima chiqaradi?

Javob

Xush kelibsiz, !, Siz dan keldingiz. va Argumentlar soni: 0. Berilmagan argument — bo'sh qator. Bash xato bermaydi, jimgina bo'sh qo'yadi. Bu xavfli bo'lishi mumkin — shuning uchun quyida argument bor-yo'qligini tekshirishni va set -u sozlamasini o'rganamiz.

3.4 Ishlayotgan paytda so'rash: read

Argument — skript boshlanishidan oldin beriladi. Ba'zan esa qiymatni ish davomida so'rash qulayroq. Buni read qiladi: u foydalanuvchi yozib, Enter bosishini kutadi va yozilganini o'zgaruvchiga soladi. sora.sh:

bash
#!/usr/bin/env bash
read -p "Ismingiz: " ism
echo "Salom, $ism!"

-p (prompt) — kutishdan oldin ko'rsatiladigan savol matni. bash sora.sh ni ishga tushirib, Jasur deb yozing:

text
Ismingiz: Jasur
Salom, Jasur!

Qaysi biri yaxshiroq? Argument — avtomatik ishlaydigan skriptlar uchun (CI, jadval bo'yicha ishga tushadigan skriptlar): u yerda klaviatura oldida hech kim o'tirmaydi. read — odam bilan "gaplashadigan" kichik yordamchi skriptlar uchun.

4. Qo'shtirnoq qoidalari

Bash'da qo'shtirnoq turi natijani o'zgartiradi. Uchta qoida yetarli.

1. Ikkitalik "..." — o'zgaruvchi ochiladi:

bash
ism="Ali"
echo "Salom, $ism"
text
Salom, Ali

2. Bittalik '...' — hamma narsa aynan qanday bo'lsa, shunday:

bash
echo 'Salom, $ism'
text
Salom, $ism

Bittalik qo'shtirnoq ichida $ oddiy belgi. Ikkitalik ichida bitta $ ni oddiy belgi qilish uchun oldiga \ qo'yiladi: "Narx: \$5" — Narx: $5.

3. O'zgaruvchini doim ikkitalik qo'shtirnoqqa oling:

bash
fayl="oylik hisobot.txt"
touch "$fayl"
ls $fayl
text
ls: cannot access 'oylik': No such file or directory
ls: cannot access 'hisobot.txt': No such file or directory

Qo'shtirnoqsiz $fayl ochilganda bo'sh joy bo'yicha ikki bo'lakka bo'lindi va ls ikkita yo'q faylni qidirdi. ls "$fayl" esa to'g'ri ishlaydi. Qoida oddiy: $ism emas — "$ism". Fayl nomlarida bo'sh joy tez-tez uchraydi, va bu qoida sizni ko'p xatodan saqlaydi.

Yozuv ism="Ali" bo'lsa natija
"Salom, $ism" Salom, Ali
'Salom, $ism' Salom, $ism
"Narx: \$5" Narx: $5

Tekshirib ko'ring: shahar="Toshkent" dan keyin echo "Men $shahar'da" va echo 'Men $shahar da' nima chiqaradi?

Javob

Birinchisi — Men Toshkent'da: ikkitalik qo'shtirnoq ichidagi apostrof oddiy belgi, o'zgaruvchi esa ochildi (apostrof nomga kirmaydi, shuning uchun ${} shart emas edi). Ikkinchisi — Men $shahar da: bittalik qo'shtirnoq ichida hech narsa ochilmaydi.

5. Shart: if

5.1 Tuzilishi

if — "agar ... bo'lsa, ... qil, aks holda ...". tekshir.sh:

bash
#!/usr/bin/env bash
if [ -f "$1" ]; then
  echo "$1 — fayl, bor."
elif [ -d "$1" ]; then
  echo "$1 — papka."
else
  echo "$1 topilmadi."
fi

Bo'laklaymiz:

  • if [ shart ]; then — "agar shart to'g'ri bo'lsa, unda".
  • elif — "aks holda, agar" (else if). Ixtiyoriy, bir nechta bo'lishi mumkin.
  • else — "aks holda". Ixtiyoriy.
  • fi — if ning oxiri (if ni teskari o'qing).
  • Ichkaridagi qatorlar ikki bo'sh joy bilan suriladi — faqat o'qish qulayligi uchun.
bash
touch menyu.txt
mkdir -p rasmlar
bash tekshir.sh menyu.txt
bash tekshir.sh rasmlar
bash tekshir.sh yoq.txt
text
menyu.txt — fayl, bor.
rasmlar — papka.
yoq.txt topilmadi.

5.2 [ ] aslida nima?

[ — aslida buyruq (test buyrug'ining boshqa nomi). U shartni tekshiradi va exit code qaytaradi: 0 — to'g'ri, 1 — noto'g'ri. if esa shunchaki exit code'ga qaraydi. Shuning uchun [ dan keyin va ] dan oldin bo'sh joy majburiy — bu buyruq va uning argumentlari.

Va shuning uchun if dan keyin istalgan buyruqni yozish mumkin: if grep -q "TODO" app.js; then ... — grep topsa (0), shart to'g'ri.

5.3 Eng ko'p kerak bo'ladigan tekshiruvlar

Fayllar va matn uchun:

Shart To'g'ri, agar
[ -f "$f" ] $f — mavjud fayl
[ -d "$d" ] $d — mavjud papka
[ -z "$s" ] $s bo'sh (zero length)
[ "$a" = "$b" ] Ikki matn teng

Sonlar uchun — so'zlar bilan (PowerShell'dagidek):

Shart Ma'nosi
-eq teng (equal)
-ne teng emas (not equal)
-gt / -ge katta / katta yoki teng
-lt / -le kichik / kichik yoki teng

Nega sonlar uchun > emas? Chunki > faylga yo'naltirish uchun band. [ $a > 5 ] yozsangiz, bash 5 degan fayl yaratadi!

bash
#!/usr/bin/env bash
son=$1
if [ "$son" -gt 100 ]; then
  echo "Katta buyurtma"
else
  echo "Oddiy buyurtma"
fi

bash son.sh 150 — Katta buyurtma, bash son.sh 5 — Oddiy buyurtma.

5.4 exit — skriptni to'xtatish va kod qaytarish

Skript ham dastur, u ham exit code qaytaradi. Odatda — oxirgi bajarilgan buyruqning kodi. O'zingiz belgilash uchun — exit N. Argument berilmasa, yo'riqnoma chiqarib, xato bilan chiqamiz:

bash
if [ $# -eq 0 ]; then
  echo "Ishlatish: ./tekshir.sh <fayl>" >&2
  exit 1
fi

>&2 — echo natijasini stderr'ga yuborish (1>&2 ning qisqasi, oqimlar darsidagi 2>&1 ning teskarisi). Xato xabarlari stderr'ga yoziladi — shunda ular natija bilan aralashmaydi. exit 1 esa chaqirgan odamga (yoki CI'ga) "muvaffaqiyatsiz" deydi.

Tekshirib ko'ring: [ "$ism" = "Ali" ] va ["$ism" = "Ali"] — qaysi biri ishlaydi?

Javob

Birinchisi. Ikkinchisida [ dan keyin bo'sh joy yo'q — bash ["Ali" ni (ya'ni [Ali) bitta buyruq nomi deb o'qiydi va [Ali: command not found xatosini beradi.

6. Sikl: for

for — ro'yxatdagi har bir element uchun bir xil ishni takrorlaydi:

bash
#!/usr/bin/env bash
for taom in osh somsa manti; do
  echo "Menyuda: $taom"
done
text
Menyuda: osh
Menyuda: somsa
Menyuda: manti
  • for taom in ... — "ro'yxatdagi har bir element uchun, uni taom deb atab".
  • do ... done — har safar bajariladigan qism.

Ro'yxat o'rnida glob juda qulay — papkadagi fayllar ustida ishlash:

bash
for fayl in *.txt; do
  echo "Topildi: $fayl"
done

Yoki skriptga berilgan barcha argumentlar ustida: for fayl in "$@"; do. "$@" qo'shtirnoqda — shunda bo'sh joyli argumentlar bo'linib ketmaydi.

Sonlar ketma-ketligi uchun: for i in {1..5}; do — 1 dan 5 gacha.

Tekshirib ko'ring: Quyidagi sikl nechta papka yaratadi va qanday nomlar bilan?

bash
for oy in yanvar fevral mart; do
  mkdir -p "hisobot/$oy"
done
Javob

Uchta: hisobot/yanvar, hisobot/fevral, hisobot/mart (va ularning ota papkasi hisobot, -p tufayli). Sikl har bir oy uchun mkdir ni bir marta bajaradi.

7. Xavfsiz skript: set -euo pipefail

7.1 Muammo: bash xatodan keyin ham davom etadi

xavfli.sh:

bash
#!/usr/bin/env bash
cd /yoq-papka
echo "Hozir shu papkadaman: $(pwd)"
text
xavfli.sh: line 2: cd: /yoq-papka: No such file or directory
Hozir shu papkadaman: /home/ali/skriptlar

cd yiqildi, lekin skript davom etdi — va noto'g'ri papkada ishlashni boshladi. Endi tasavvur qiling, ikkinchi qator echo emas, rm -rf * bo'lsa. Bash kerakli papkani emas, siz turgan papkani tozalab tashlardi — skriptni uy papkangizdan ishga tushirgan bo'lsangiz, uy papkangizni. Bu — exit code darsidagi ; muammosining o'zi: skriptdagi qatorlar odatda ; bilan ajratilgandek bajariladi.

7.2 Yechim

Skript boshiga, shebang'dan keyin bitta qator:

bash
#!/usr/bin/env bash
set -euo pipefail
cd /yoq-papka
echo "Bu qator chiqmaydi"
text
xavfsiz.sh: line 3: cd: /yoq-papka: No such file or directory

Skript cd da to'xtadi va exit code 1 qaytardi. Uchta sozlama:

Sozlama Nima qiladi
-e Birorta buyruq xato bersa (0 emas) — skript to'xtaydi
-u Yaratilmagan o'zgaruvchi ishlatilsa — xato
-o pipefail Pipe'dagi birorta bo'lak yiqilsa — butun zanjir xato

-u ning foydasi: $ism da harf xatosi qilsangiz ($ims), bash jimgina bo'sh qo'ymaydi, balki ims: unbound variable ("bog'lanmagan o'zgaruvchi") deb to'xtaydi. pipefail ni exit code darsida ko'rgan edik.

Qoida: har bir yangi skript shu ikki qator bilan boshlansin:

bash
#!/usr/bin/env bash
set -euo pipefail

Diqqat: set -u bilan $1 ga to'g'ridan-to'g'ri murojaat argument berilmasa xato beradi ($1: unbound variable). Shuning uchun argumentlarni avval $# bilan tekshiring — $# doim mavjud.

8. Mini-loyiha: zaxira.sh

Endi 1-bo'limdagi vazifaga qaytamiz. Hamma bo'lakni birlashtiramiz:

bash
#!/usr/bin/env bash
set -euo pipefail

if [ $# -eq 0 ]; then
  echo "Ishlatish: ./zaxira.sh <papka>" >&2
  exit 1
fi

manba="$1"
sana=$(date +%Y-%m-%d)
nusxa="zaxira/${manba}-${sana}"

mkdir -p zaxira
cp -r "$manba" "$nusxa"
echo "Tayyor: $nusxa"

Qator-qator:

  1. Shebang va xavfsizlik sozlamasi.
  2. Argument yo'q bo'lsa — yo'riqnoma stderr'ga, exit 1.
  3. manba — nusxalanadigan papka, sana — bugungi sana (2026-09-27 ko'rinishida — bunday tartib fayllarni sana bo'yicha to'g'ri saralaydi).
  4. nusxa — nusxa yo'li, ${} bilan chegaralangan.
  5. mkdir -p — zaxira papkasini yaratadi (bor bo'lsa, jim).
  6. cp -r — papkani ichidagilari bilan nusxalaydi. O'zgaruvchilar qo'shtirnoqda.

Sinab ko'ramiz:

bash
chmod +x zaxira.sh
mkdir -p sayt
touch sayt/index.html
./zaxira.sh
./zaxira.sh sayt
./zaxira.sh yoqpapka
text
Ishlatish: ./zaxira.sh <papka>
Tayyor: zaxira/sayt-2026-09-27
cp: cannot stat 'yoqpapka': No such file or directory

Uchinchi holatda cp yiqildi va set -e skriptni to'xtatdi — Tayyor degan yolg'on xabar chiqmadi.

9. Ko'p uchraydigan xatolar

9.1 = atrofida bo'sh joy

text
skript.sh: line 2: ism: command not found

ism = "Ali" yozilgan. Muhit o'zgaruvchilari darsidagidek: bash ism ni buyruq deb o'qidi. Tuzatish: ism="Ali".

9.2 [ yonida bo'sh joy yo'q

text
skript.sh: line 1: [prod: command not found

if ["$1" = "prod"] yozilgan. [ — buyruq, u so'zdan bo'sh joy bilan ajralishi shart. Tuzatish: if [ "$1" = "prod" ].

9.3 Qo'shtirnoqsiz bo'sh o'zgaruvchi

text
skript.sh: line 3: [: =: unary operator expected

if [ $rejim = "prod" ] yozilgan, rejim esa bo'sh. Qo'shtirnoqsiz bo'sh o'zgaruvchi "yo'qolib", bash [ = "prod" ] ni ko'rdi va chalkashdi. Tuzatish: [ "$rejim" = "prod" ] — endi u [ "" = "prod" ] bo'ladi va shunchaki "noto'g'ri" deydi.

9.4 Songa matn berish

bash
bash son.sh abc
text
son.sh: line 3: [: abc: integer expression expected

"Butun son kutilgan edi" (bash 5.3 da xabar qisqaroq: integer expected). -gt faqat sonlar bilan ishlaydi. Foydalanuvchi nima berishini oldindan bilmaysiz — muhim skriptlarda argumentni tekshiring.

9.5 Windows'da yozilgan skript Linux'da ishlamaydi

Skriptni Windows'da yozib, serverga ko'chirdingiz va:

text
/usr/bin/env: 'bash\r': No such file or directory

"bash\r topilmadi". \r — qator oxiri darsidagi CR belgisi: fayl Windows qator oxiri (CRLF) bilan saqlangan. Linux shebang'ni bash\r deb o'qidi. Git Bash buni kechiradi, Linux — yo'q. Tuzatish: VS Code'ning pastki o'ng burchagida CRLF ni LF ga almashtiring yoki dos2unix skript.sh.

9.6 Permission denied

text
bash: ./zaxira.sh: Permission denied

Linux, macOS yoki WSL'da chmod +x qilinmagan (exit code 126). Tuzatish: chmod +x zaxira.sh yoki bash zaxira.sh.

10. Mashqlar

1-mashq (oson): Bo'sh joylarni to'ldiring

salom.sh skripti birinchi argumentdagi ism bilan salomlashsin va argumentlar sonini aytsin. Bo'sh joylarni to'ldiring:

  • Birinchi argument saqlanadigan o'zgaruvchi: $
  • Argumentlar soni saqlanadigan o'zgaruvchi: $
  • Linux'da faylga bajarish huquqini berish: chmod salom.sh

Keyin skriptni to'liq yozing: shebang, xavfsizlik qatori va ikkita echo.

Yechim
bash
#!/usr/bin/env bash
set -euo pipefail
echo "Salom, $1!"
echo "Argumentlar soni: $#"

bash salom.sh Jasur natijasi:

text
Salom, Jasur!
Argumentlar soni: 1

$1 — birinchi argument, $# — argumentlar soni. chmod +x — bajarish huquqi. Diqqat: set -u tufayli argumentsiz ishga tushirsangiz, $1: unbound variable xatosi chiqadi — bu kutilgan xatti-harakat.

2-mashq (o'rta): Oylik papkalar

oylar.sh skriptini yozing. U for sikli bilan hisobot/yanvar, hisobot/fevral, hisobot/mart papkalarini yaratsin va har biri uchun Yaratildi: hisobot/yanvar kabi xabar chiqarsin. Skript xavfsizlik qatori bilan boshlansin.

Yechim
bash
#!/usr/bin/env bash
set -euo pipefail

for oy in yanvar fevral mart; do
  mkdir -p "hisobot/$oy"
  echo "Yaratildi: hisobot/$oy"
done
text
Yaratildi: hisobot/yanvar
Yaratildi: hisobot/fevral
Yaratildi: hisobot/mart

-p ikki ishni qiladi: hisobot yo'q bo'lsa — yaratadi, papka allaqachon bor bo'lsa — xato bermaydi. Shuning uchun skriptni ikkinchi marta ishga tushirsangiz ham set -e uni to'xtatmaydi.

3-mashq (qiyin): Fayl hisobchisi

hisob.sh skriptini yozing. Unga bir nechta fayl nomi beriladi. Har bir fayl uchun:

  • fayl bor bo'lsa — yanvar.txt: 2 qator ko'rinishida qatorlar sonini chiqarsin;
  • yo'q bo'lsa — mart.txt: topilmadi xabarini stderr'ga yozsin.

Argument umuman berilmasa — yo'riqnoma chiqarib, exit 1.

Ishoralar: barcha argumentlar — "$@"; qatorlar soni — oqimlar darsidagi wc -l < fayl (fayl nomisiz faqat son beradi); buyruq natijasini matnga qo'yish — $(...).

Tekshirish uchun: printf "a\nb\n" > yanvar.txt va touch fevral.txt, keyin bash hisob.sh yanvar.txt fevral.txt mart.txt.

Yechim
bash
#!/usr/bin/env bash
set -euo pipefail

if [ $# -eq 0 ]; then
  echo "Ishlatish: ./hisob.sh <fayl>..." >&2
  exit 1
fi

for fayl in "$@"; do
  if [ -f "$fayl" ]; then
    echo "$fayl: $(wc -l < "$fayl") qator"
  else
    echo "$fayl: topilmadi" >&2
  fi
done
text
yanvar.txt: 2 qator
fevral.txt: 0 qator
mart.txt: topilmadi
  • $# -eq 0 — argumentlar soni nolga tengmi.
  • for fayl in "$@" — har bir argument ustida; qo'shtirnoq bo'sh joyli nomlarni saqlaydi.
  • $(wc -l < "$fayl") — < bilan wc faqat sonni beradi, $(...) uni satrga qo'yadi. macOS'da wc sondan oldin bo'sh joylar qo'yadi (yanvar.txt: 2 qator) — bu xato emas, shunchaki boshqacha ko'rinish.
  • >&2 — "topilmadi" xabari stderr'ga. Tekshirish: bash hisob.sh yanvar.txt mart.txt 2> /dev/null — mart.txt qatori yo'qoladi.

11. Real ishda

  • Deploy skriptlari. Serverga yangi versiyani chiqarish ko'pincha deploy.sh bilan: kodni yangilash, bog'liqliklarni o'rnatish, qayta ishga tushirish. Uning birinchi ikki qatori — xuddi shu darsdagidek.
  • Zaxira va tozalash. Serverda har kecha avtomatik ishlaydigan skriptlar: bazaning zaxirasi, eski loglarni o'chirish. Ularni jadval bo'yicha ishga tushirishni server qismida o'rganamiz.
  • CI. GitHub Actions ichidagi har bir qadam — aslida kichik bash skript. Exit code va set -e u yerda ham hal qiluvchi.
  • ShellCheck. Skriptlaringizni tekshiradigan bepul vosita (shellcheck skript.sh, VS Code kengaytmasi ham bor). U qo'shtirnoqsiz $fayl kabi xatolarni ishga tushirishdan oldin topadi.
  • Qachon skript emas? Mantiq murakkablashsa (JSON bilan ishlash, ko'p shartlar) — Node.js yoki Python'da yozgan ma'qul. Bash — buyruqlarni bog'lash uchun, katta dasturlar uchun emas.

Xulosa

  • Shell skript — buyruqlar yozilgan fayl; boshida #!/usr/bin/env bash va set -euo pipefail.
  • Ishga tushirish: bash skript.sh yoki chmod +x dan keyin ./skript.sh (./ — chunki joriy papka PATH'da yo'q).
  • Argumentlar: $1, $2, $# (soni), "$@" (hammasi); ish davomida so'rash — read -p; buyruq natijasi — $(buyruq); hisob — $((...)).
  • "..." ichida o'zgaruvchi ochiladi, '...' ichida — yo'q; o'zgaruvchini doim "$nom" deb yozing.
  • if [ shart ]; then ... fi — [ atrofida bo'sh joy majburiy; sonlar — -eq, -gt, -lt.
  • for x in ...; do ... done — ro'yxat, glob yoki argumentlar ustida takrorlash.

Keyingi dars: Zamonaviy CLI vositalari — klassik buyruqlarning tezroq va qulayroq zamonaviy muqobillari bilan tanishamiz.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Shell skript yozish asoslari: bash'da birinchi avtomatlashtirish — IlmHamroh