Mundarija (34)
- Bu darsda
- 1. Nega bu kerak?
- 2. Tashqi buyruq chaqirish
- 2.1 child_process va Windows tuzog'i
- 2.2 execa
- 2.3 zx va biz topgan Windows tuzog'i
- 3. Fayllar bilan ommaviy ish
- 3.1 O'rnatilganlari va kutubxonalar
- 3.2 Ommaviy qayta nomlash
- 3.3 Zaxira skripti
- 4. Vaqt bo'yicha ishga tushirish
- 4.1 cron (Linux, macOS)
- 4.2 Windows Task Scheduler
- 4.3 Node ichida: node-cron
- 5. CLI qadami: nashrdan oldingi tekshiruv skripti (holat 55 ga)
- 5.1 Muammo
- 5.2 scripts/paket-tekshir.mjs
- 5.3 package.json ga ulash
- 5.4 Bitta ESLint tuzatishi
- 6. Ko'p uchraydigan xatolar
- 6.1 ENOENT / EINVAL — Windows'da npm
- 6.2 WSL … execvpe(/bin/bash) failed
- 6.3 Glob Windows'da "ko'proq" topadi
- 6.4 Yo'llarni satr qo'shish bilan yasash
- 6.5 Cron'da "ishlamayapti", qo'lda — ishlaydi
- 6.6 Skript xatoda 0 bilan tugadi
- 7. Mashqlar
- 1-mashq (oson): to'g'ri vositani tanlang
- 2-mashq (o'rta): quruq ishga tushirish
- 3-mashq (qiyin): eski zaxiralarni tozalash
- 4-mashq: CLI qadami — paket:tekshir
- 8. Real ishda
- Xulosa
- Manbalar
Node.js skriptlar: bash o'rniga JavaScript bilan avtomatlashtirish (zx, execa, fs.glob)
Qisqacha: Takrorlanadigan ishni (fayllarni qayta nomlash, zaxira, nashrdan oldingi tekshiruv) bash o'rniga Node skripti bilan yozsangiz, u Windows, macOS va Linux'da bir xil ishlaydi. Node 24 da ko'p narsa o'rnatilgan:
fs.glob,fs.cp,mkdir({ recursive }),child_process. Tashqi dastur chaqirish uchun execa (Windows'daginpm.cmdmuammosini o'zi hal qiladi) yoki zx ($`buyruq`sintaksisi — lekin ichida bash kerak). Skriptni vaqt bo'yicha ishga tushirish — Linux'da cron, Windows'da Task Scheduler.
Bu darsda
- Bash skriptni qachon Node skripti bilan almashtirish kerakligini tushuntira olasiz.
child_process, execa va zx bilan tashqi buyruq chaqirasiz va Windows'dagi uchta tuzoqni bilasiz.fs.glob,fs.cp,renamebilan ommaviy qayta nomlash va zaxira skriptini yozasiz.- Skriptni cron va Windows Task Scheduler bilan rejalashtirish yo'lini bilasiz.
valyutauchun nashrdan oldingi tekshiruv skriptini (scripts/paket-tekshir.mjs) tushunasiz.
Oldin bilishingiz kerak: child_process: tashqi dasturlarni ishga tushirish, fs chuqur: kataloglar, stat, glob va watch, path va os: kross-platforma kod, Node'da CLI dastur anatomiyasi.
1. Nega bu kerak?
Dasturchi ishining bir qismi — takrorlanadigan mayda ishlar. Har nashrdan oldin: build, test, paket hajmini tekshirish. Har hafta: kesh papkasini zaxiralash. To'ydan keyin: 800 ta IMG_0001.JPG ni toy-001.jpg qilish.
An'anaviy vosita — bash skript. Muammo: Windows. cp -r, find, sed u yerda yo'q yoki boshqacha ishlaydi. Jamoangizda bitta Windows'chi bo'lsa, bash skript uning uchun ishlamaydi. Node esa hammada bor — siz uni allaqachon loyiha uchun o'rnatgansiz.
Ikkinchi sabab — xatolar. Bash'da rm -rf $PAPKA/ — o'zgaruvchi bo'sh bo'lsa, rm -rf / bo'ladi. JavaScript'da yo'l — qiymat, uni tekshirish, test yozish oson.
O'xshatish: retsept. Bash skript — faqat bitta oshxonadagi pechga mos retsept ("3-tugmani bosing"). Node skripti — har qanday oshxonada ishlaydigan retsept ("180 darajada 20 daqiqa").
2. Tashqi buyruq chaqirish
2.1 child_process va Windows tuzog'i
child_process darsida execFile va spawn ni ko'rgansiz. Skriptlarda eng ko'p kerak bo'ladigan buyruq — npm. Windows'da biz sinadik:
import { execFileSync } from "node:child_process";
try {
execFileSync("npm", ["--version"], { encoding: "utf8" });
} catch (x) {
console.log(x.code);
}
try {
execFileSync("npm.cmd", ["--version"], { encoding: "utf8" });
} catch (x) {
console.log(x.code);
}ENOENT
EINVALWindows'da npm — bu npm.cmd fayli. Birinchi xato ENOENT: npm nomli bajariladigan fayl yo'q. Ikkinchisi EINVAL: Node xavfsizlik sababli .cmd faylni shell'siz ishga tushirmaydi. shell: true bilan ishlaydi, lekin kanon tajribasi (t25-child.txt) ko'rsatgan: Node 24 bunda DEP0190 ogohlantirishini beradi (argumentlar shell orqali o'tadi — injection xavfi). Linux'da execFileSync("npm", …) to'g'ridan ishlaydi (hujjat bo'yicha; sinamadik).
Kanon yechimi — npm'ning o'z JS faylini Node bilan chaqirish. npm run … ichida npm o'z yo'lini npm_execpath muhit o'zgaruvchisiga yozadi:
const npmJs = process.env.npm_execpath;
const args = [npmJs, "pack", "--dry-run", "--json"];
execFileSync(process.execPath, args);process.execPath — hozirgi node fayli. Shell yo'q, .cmd yo'q, har OS'da bir xil.
2.2 execa
execa (10.1.1) — child_process ustidagi qulay qatlam. Windows'dagi .cmd muammosini ichkarida hal qiladi:
import { execa } from "execa";
const { stdout } = await execa("npm", ["--version"]);
console.log("npm:", stdout);
const r = await execa("node", ["-e", "process.exit(3)"], {
reject: false,
});
console.log("exit:", r.exitCode, r.failed);Biz Windows'da ishga tushirdik:
npm: 11.19.0
exit: 3 truenpm to'g'ridan ishladi. reject: false — exit kod 0 bo'lmasa xato tashlamaydi, natijani qaytaradi: failed: true va exitCode: 3. Sukut bo'yicha esa execa xato tashlaydi — skript birinchi muvaffaqiyatsiz qadamda to'xtaydi. Bu bash'dagi set -e ning yaxshi versiyasi.
2.3 zx va biz topgan Windows tuzog'i
zx (8.8.5, Google) — skriptni bash'ga o'xshatadi:
import { $ } from "zx";
const v = await $`node --version`;
console.log("node:", v.stdout.trim());
const n = await $`npm --version`;
console.log("npm:", n.stdout.trim());
const fayl = "bo'sh joyli nom.txt";
await $`echo salom > ${fayl}`;
console.log((await $`cat ${fayl}`).stdout.trim());Git Bash ochiq terminalda — ishladi: node: v24.21.0, npm: 11.19.0, salom. ${fayl} — zx o'zgaruvchini avtomatik qo'shtirnoqqa oladi, shuning uchun bo'sh joyli nom buzilmadi. Bu — zx'ning asosiy qulayligi.
Lekin zx buyruqni bash orqali bajaradi. PATH'da Git Bash bo'lmagan Windows'da (oddiy PowerShell yoki cmd) biz shuni oldik:
<3>WSL (10 - Relay) ERROR: CreateProcessCommon:798: execvpe(/bin/bash) failed: No such file or directoryNima bo'ldi? zx bash ni qidirdi va C:\Windows\System32\bash.exe ni topdi — bu WSL (Windows ichidagi Linux) ishga tushiruvchisi. Bizning mashinada WSL ichida bash yo'q edi, natijada tushunarsiz xato. Yechim — usePowerShell():
import { $, usePowerShell } from "zx";
usePowerShell();
const v = await $`node --version`;
console.log("node:", v.stdout.trim());Bu ishladi (node: v24.21.0). Lekin endi buyruqlar PowerShell sintaksisida — cat, > boshqacha. Ya'ni zx'da "bitta skript hamma joyda" va'dasi buyruqlar ichida buziladi.
flowchart TD
A["Skript tashqi buyruq chaqiradi"] --> B{"Faqat Node va npm?"}
B -- "ha" --> C["child_process + process.execPath"]
B -- "yo'q" --> D{"Ko'p buyruq, shell qulayligi kerak?"}
D -- "ha" --> E["zx — bash bor joyda"]
D -- "yo'q" --> F["execa — har OS'da"]Tekshirib ko'ring: Jamoangizda hamma Mac'da, CI esa Linux. zx tanlash xavflimi?
Javob
Kam xavfli: hamma joyda bash bor va zx aynan shunday muhit uchun. Xavf keyin paydo bo'ladi — birinchi Windows'chi qo'shilganda. Shuning uchun README'da "Git Bash kerak" deb yozing yoki skript ichidagi buyruqlarni Node API'lariga (fs, execa) o'tkazing.
3. Fayllar bilan ommaviy ish
3.1 O'rnatilganlari va kutubxonalar
| Ish | Node 24 da | Kutubxona (versiya — npm view, 2026-10-23) |
|---|---|---|
| Naqsh bo'yicha qidirish | fs.glob |
fast-glob, tinyglobby 0.2.17 |
| Papkani nusxalash | fs.cp(…, { recursive: true }) |
fs-extra 11.4.1 (copy) |
| Ichma-ich papka yaratish | mkdir(…, { recursive: true }) |
fs-extra (ensureDir) |
| O'chirish | rm(…, { recursive: true, force: true }) |
rimraf |
Bir necha yil oldin chap ustun bo'sh edi — shuning uchun eski loyihalarda o'ng ustundagilarni ko'rasiz. Masalan fs.glob Node 22 da eksperimental bo'lib kelgan va hujjatga ko'ra faqat Node 24.0 da barqaror (stable) deb belgilangan. Yangi skriptda avval chap ustun. valyuta kanoni ham fs.glob ishlatgan (fs chuqur).
3.2 Ommaviy qayta nomlash
Vazifa: rasmlar/ dagi har xil yozilgan .jpg fayllarni tartib bilan toy-01.jpg, toy-02.jpg … qilish, .txt ga tegmaslik.
import { mkdir, writeFile, rename, glob, rm } from "node:fs/promises";
import { join, basename, extname } from "node:path";
// sinov papkasi: telefondan tushgan to'y rasmlari
await rm("rasmlar", { recursive: true, force: true });
await mkdir("rasmlar");
const nomlar = ["IMG_0003.JPG", "IMG_0001.jpg", "IMG_0002.Jpg",
"izoh.txt"];
for (const n of nomlar) await writeFile(join("rasmlar", n), "");
const rasmlar = [];
for await (const f of glob("rasmlar/*")) {
if (extname(f).toLowerCase() === ".jpg") rasmlar.push(f);
}
rasmlar.sort();
let n = 1;
for (const eski of rasmlar) {
const raqam = String(n++).padStart(2, "0");
const yangi = join("rasmlar", `toy-${raqam}.jpg`);
await rename(eski, yangi);
console.log(`${basename(eski)} → ${basename(yangi)}`);
}
await rm("rasmlar", { recursive: true });Konsolda:
IMG_0001.jpg → toy-01.jpg
IMG_0002.Jpg → toy-02.jpg
IMG_0003.JPG → toy-03.jpgUch tafsilot:
- Kengaytmani o'zimiz tekshirdik,
glob("rasmlar/*.jpg")emas. Sabab — biz topgan farq: Windows'da*.jpgnaqshiA.JPG,b.jpg,c.Jpguchalasini topdi (fayl tizimi katta-kichik harfni farqlamaydi). Linux'da esa faqatb.jpgni topadi (hujjat bo'yicha; sinamadik).extname(f).toLowerCase()ikkala OS'da bir xil. sort()—globtartibni va'da qilmaydi. Tartib muhim bo'lsa, o'zingiz saralang.basename— Windows'daglobrasmlar\IMG_0001.jpgqaytaradi (teskari chiziq), Linux'da/. Chiqishda faqat nomni ko'rsatdik.
Skript boshida papkani tozalab yaratdik — uni necha marta ishga tushirsangiz ham natija bir xil. Bu xususiyatning nomi idempotentlik: takror ishga tushirish holatni buzmaydi. Avtomatik skript uchun juda muhim — u ikki marta ishga tushib qolishi mumkin.
Diqqat: Ommaviy
rename— qaytarib bo'lmaydigan amal. Haqiqiy skriptda avval quruq ishga tushirish (dry run) qiling:--sinovbayrog'i bilan faqat "nima bo'lardi"ni chiqarsin. Va nom to'qnashuvini tekshiring:toy-01.jpgallaqachon bor bo'lsa,renameuni jim ustiga yozadi (hujjat bo'yicha, Windows'da ham Linux'da ham almashtiradi).
3.3 Zaxira skripti
Kesh papkasini sana bilan nomlangan nusxaga ko'chirish:
import { mkdir, writeFile, cp, readdir, rm } from "node:fs/promises";
import { join } from "node:path";
// sinov: kesh papkasi
await rm("kesh", { recursive: true, force: true });
await rm("zaxiralar", { recursive: true, force: true });
await mkdir("kesh/tarix", { recursive: true });
await writeFile("kesh/kurslar.json", "[]");
await writeFile("kesh/tarix/USD-2026-10-01.json", "[]");
function zaxiraNomi(sana) {
return `kesh-${sana.toISOString().slice(0, 10)}`;
}
const nom = zaxiraNomi(new Date("2026-10-23T03:00:00Z"));
const manzil = join("zaxiralar", nom);
await cp("kesh", manzil, { recursive: true });
const fayllar = await readdir(manzil, { recursive: true });
console.log(nom);
console.log(fayllar.map((f) => f.replaceAll("\\", "/")).sort());
await rm("kesh", { recursive: true });
await rm("zaxiralar", { recursive: true });Konsolda:
kesh-2026-10-23
[ 'kurslar.json', 'tarix', 'tarix/USD-2026-10-01.json' ]Misolda sanani qat'iy berdik — natija har kuni bir xil bo'lsin. Haqiqiy skriptda zaxiraNomi(new Date()). Nom YYYY-MM-DD ko'rinishida — alifbo tartibi vaqt tartibiga teng, eng eski zaxira ro'yxat boshida. replaceAll("\\", "/") — Windows yo'llarini bir xil ko'rinishga keltirish (path va os).
Haqiqiy zaxirada yana ikki narsa kerak: eski zaxiralarni o'chirish (masalan, 7 kundan eskisini — mashqda) va natijani logga yozish.
Tekshirib ko'ring: Zaxira nomini
kesh-23.10.2026(kun.oy.yil) qilsak nima yomon?
Javob
Alifbo tartibi buziladi: kesh-01.11.2026 (1-noyabr) kesh-23.10.2026 dan oldin turadi. "Eng eskisini o'chir" mantiqi noto'g'ri faylni o'chiradi. YYYY-MM-DD (ISO 8601) — matn sifatida saralanganda ham to'g'ri tartib beradi.
4. Vaqt bo'yicha ishga tushirish
4.1 cron (Linux, macOS)
cron — Linux'ning vaqt rejalashtiruvchisi. crontab -e da bitta qator:
0 3 * * * cd /home/ali/valyuta && /usr/bin/node scripts/zaxira.mjs >> zaxira.log 2>&1Besh maydon: daqiqa (0), soat (3), oy kuni, oy, hafta kuni (* — har qanday). Ya'ni har kuni 03:00 da. Hujjat bo'yicha; biz Linux'da sinamadik.
Ikki tuzoq: cron'da PATH qisqa — node ni to'liq yo'l bilan yozing (which node), va joriy papka uy papkasi — cd kerak. >> zaxira.log 2>&1 — stdout va stderr faylga, aks holda xatolarni hech kim ko'rmaydi.
4.2 Windows Task Scheduler
Windows'da — Task Scheduler (Vazifalar rejalashtiruvchisi). Buyruq qatoridan:
schtasks /Create /SC DAILY /ST 03:00 /TN "valyuta zaxira" /TR "node C:\Users\…\valyuta\scripts\zaxira.mjs"Hujjat bo'yicha keltirildi — biz bu vazifani yaratmadik (zavod qoidasi: tizimda doimiy sozlama qoldirilmaydi). Grafik oynada ham shu: "Create Basic Task" → kunlik → dastur node, argument — skript yo'li.
4.3 Node ichida: node-cron
Uzoq yashaydigan Node jarayoni (server) ichida vazifa kerak bo'lsa — node-cron kabi kutubxonalar cron sintaksisini Node ichida bajaradi. Bu faqat jarayon ishlab turganda ishlaydi: server o'chsa, vazifa ham yo'q. Bitta skript uchun OS rejalashtiruvchisi ishonchliroq. Backend qismlarida fon vazifalari mavzusida qaytamiz.
5. CLI qadami: nashrdan oldingi tekshiruv skripti (holat 55 ga)
5.1 Muammo
Har nashrdan oldin qo'lda: npm pack --dry-run ro'yxatiga qarash ("src/ kirib qolmadimi? README bormi?"), hajmni tekshirish, --version ni package.json bilan solishtirish. Qo'lda — unutiladi. npm paket darsida publint va attw ni ko'rgansiz; ular paket tuzilmasini tekshiradi. Bizga esa o'z loyihamizning qoidalari kerak.
5.2 scripts/paket-tekshir.mjs
Kanon skripti (to'liq, .mjs — build'siz, Node'ning o'zi):
// Nashrdan oldin paketni tekshirish (bash o'rniga Node — Windows/Linux'da
// bir xil): npm pack --dry-run --json ro'yxati, hajm, bin, versiya.
// Ishga tushirish: npm run paket:tekshir (prepublishOnly ichida ham)
import { execFileSync } from "node:child_process";
import { readFileSync } from "node:fs";
const CHEGARA_KB = 50;
const paket = JSON.parse(readFileSync("package.json", "utf8"));
// Windows'da npm.cmd ni shell'siz ishga tushirib bo'lmaydi (EINVAL) —
// npm'ning o'z JS faylini node bilan chaqiramiz
const npmJs = process.env.npm_execpath;
if (!npmJs) throw new Error("npm orqali ishga tushiring: npm run paket:tekshir");
const [natija] = JSON.parse(execFileSync(process.execPath, [npmJs, "pack", "--dry-run", "--json", "--ignore-scripts"], { encoding: "utf8" }));
const fayllar = natija.files.map((f) => f.path);
const xatolar = [];
for (const kerak of ["dist/bin.js", "dist/index.js", "dist/index.d.ts", "fixtures/kurslar-2026-10-23.json", "README.md", "LICENSE"]) {
if (!fayllar.includes(kerak)) xatolar.push(`paketda yo'q: ${kerak}`);
}
for (const f of fayllar) if (/^(src|test|scripts)\//.test(f) || f.endsWith(".tgz") || f.startsWith(".env")) xatolar.push(`paketga tushmasligi kerak: ${f}`);
if (natija.size > CHEGARA_KB * 1024) xatolar.push(`hajm ${String(natija.size)} bayt > ${String(CHEGARA_KB)} kB`);
if (!readFileSync(paket.bin.valyuta, "utf8").startsWith("#!/usr/bin/env node")) xatolar.push(`${paket.bin.valyuta}: shebang yo'q`);
const versiya = execFileSync(process.execPath, [paket.bin.valyuta, "--version"], { encoding: "utf8" }).trim();
if (versiya !== paket.version) xatolar.push(`--version ${versiya}, package.json ${paket.version}`);
console.log(`${natija.name}@${natija.version}: ${String(fayllar.length)} fayl, ${(natija.size / 1024).toFixed(1)} kB (ochilgan ${(natija.unpackedSize / 1024).toFixed(1)} kB)`);
if (xatolar.length) {
for (const x of xatolar) console.error(`XATO: ${x}`);
process.exitCode = 1;
} else console.log("Paket tayyor.");Kod qatorlari kanondagidek (uzun qatorlar — aynan iqtibos; faqat bosh izohni bo'ldik). Bo'laklab:
| Qism | Nima tekshiradi |
|---|---|
npm pack --dry-run --json |
npm aynan qaysi fayllarni qadoqlashi — JSON ro'yxat |
--ignore-scripts |
prepack (build) qayta ishga tushmasin |
| majburiy ro'yxat | dist, .d.ts, fixture, README, LICENSE bor |
| taqiq ro'yxati | src/, test/, scripts/, .tgz, .env — yo'q |
| hajm | 50 kB dan oshmasin |
| shebang | CLI anatomiyasi darsidagi tuzoqqa qarshi |
--version |
package.json bilan bir xil (eski build qolmagan) |
Xato bo'lsa — har biri stderr'ga va process.exitCode = 1. Bitta xatoda to'xtamaydi: hammasini birdan ko'rsatadi.
5.3 package.json ga ulash
"paket:tekshir": "node scripts/paket-tekshir.mjs",
"prepublishOnly": "npm run check && npm run paket:tekshir"prepublishOnly — npm uni npm publish dan oldin o'zi chaqiradi. Xato bo'lsa, nashr bo'lmaydi. Tekshiruv endi esdan chiqmaydi.
Biz yakuniy holat nusxasida ishga tushirdik (Node 24.21.0, npm 11.19.0):
> valyuta@1.0.0 paket:tekshir
> node scripts/paket-tekshir.mjs
valyuta@1.0.0: 61 fayl, 29.4 kB (ochilgan 110.1 kB)
Paket tayyor.29.4 kB — npm pack ko'rsatgan 30.2 kB bilan bir xil hajm: skript 1024 ga, npm 1000 ga bo'ladi.
5.4 Bitta ESLint tuzatishi
Skript qo'shilgach npm run lint yiqildi: typescript-eslint'ning tur bilan tekshiruvi .mjs faylni "not found by the project service" deb rad etdi — u tsconfig loyihasida yo'q. Kanon tuzatishi — .mjs ni tur tekshiruvsiz fayllar ro'yxatiga qo'shish (eslint.config.js):
- { files: ["**/*.js"], extends: [tseslint.configs.disableTypeChecked] },
+ { files: ["**/*.js", "**/*.mjs"], extends: [tseslint.configs.disableTypeChecked], languageOptions: { globals: { process: "readonly", console: "readonly" } } },globals — process va console ni ESLint tanisin.
Bu o'zgarishlar holat 55 ga kiradi. Commit — CLI'ni tarqatish darsida (README va LICENSE bilan birga). Hozircha commit qilmang.
6. Ko'p uchraydigan xatolar
6.1 ENOENT / EINVAL — Windows'da npm
execFile("npm") → ENOENT, execFile("npm.cmd") → EINVAL. Yechim: process.execPath + npm_execpath, yoki execa.
6.2 WSL … execvpe(/bin/bash) failed
zx Git Bash'siz Windows'da WSL'ning bash.exe sini topdi. Git Bash'ni PATH'ga qo'ying yoki usePowerShell().
6.3 Glob Windows'da "ko'proq" topadi
*.jpg Windows'da .JPG ni ham oladi, Linux'da — yo'q. Kengaytmani toLowerCase() bilan o'zingiz tekshiring.
6.4 Yo'llarni satr qo'shish bilan yasash
"zaxiralar/" + nom — Windows'da ishlaydi, lekin "C:\\" + … va / aralashib ketadi. Har doim path.join.
6.5 Cron'da "ishlamayapti", qo'lda — ishlaydi
Cron'ning PATH va joriy papkasi boshqa. To'liq yo'llar va logga yozish.
6.6 Skript xatoda 0 bilan tugadi
try/catch bilan xato "yutildi", exit 0. Rejalashtiruvchi va CI buni muvaffaqiyat deb biladi. Xatoda process.exitCode = 1.
7. Mashqlar
Mashqlar kurs/mashqlar/24/53-skriptlash/ da.
1-mashq (oson): to'g'ri vositani tanlang
Har vazifa uchun eng sodda vositani ayting: fs/child_process (o'rnatilgan), execa yoki zx.
- Papkadagi
.logfayllarni sanash. - Windows va Linux'da
npm testni chaqirib, exit kodni olish. - Faqat Mac'chilar jamoasida
git,docker,curlni ketma-ket chaqiradigan 30 qatorlik skript. - Kesh papkasini nusxalash.
Yechim
fs.globyokireaddir— tashqi dastur kerak emas.- execa (yoki
process.execPath+npm_execpath) — Windows'dagi.cmdmuammosi tufayli. - zx — hamma joyda bash bor, shell sintaksisi qulay.
fs.cp(…, { recursive: true })— Node 24 da o'rnatilgan.
2-mashq (o'rta): quruq ishga tushirish
«Ommaviy qayta nomlash» skriptini funksiyaga aylantiring: rejaTuz(nomlar, prefiks) — fayl nomlari ro'yxatidan [eski, yangi] juftlari ro'yxatini qaytarsin (fayl tizimiga tegmaydi). Faqat .jpg (katta-kichik harfsiz), saralangan, raqam ikki xonali. Agar yangi nom ro'yxatdagi boshqa faylning eski nomi bilan to'qnashsa — "TO'QNASHUV" deb belgilansin. Sinov: ["IMG_2.JPG", "toy-01.jpg", "IMG_1.jpg", "a.txt"], prefiks toy. Yordam: Set va has (Set).
Yechim
function rejaTuz(nomlar, prefiks) {
const rasmlar = nomlar
.filter((n) => n.toLowerCase().endsWith(".jpg"))
.sort();
const bor = new Set(nomlar);
return rasmlar.map((eski, i) => {
const yangi = `${prefiks}-${String(i + 1).padStart(2, "0")}.jpg`;
const toqnash = yangi !== eski && bor.has(yangi);
return [eski, toqnash ? `${yangi} (TO'QNASHUV)` : yangi];
});
}
const nomlar = ["IMG_2.JPG", "toy-01.jpg", "IMG_1.jpg", "a.txt"];
for (const [eski, yangi] of rejaTuz(nomlar, "toy")) {
console.log(`${eski} → ${yangi}`);
}Konsolda:
IMG_1.jpg → toy-01.jpg (TO'QNASHUV)
IMG_2.JPG → toy-02.jpg
toy-01.jpg → toy-03.jpgTo'qnashuv topildi: IMG_1.jpg ni toy-01.jpg qilsak, mavjud toy-01.jpg ning ustiga yoziladi va bitta rasm yo'qoladi. Quruq ishga tushirish aynan shuni oldindan ko'rsatadi. Haqiqiy skriptda reja to'qnashuvsiz bo'lmaguncha rename chaqirilmaydi. Yana bir narsa: "IMG_1.jpg" < "IMG_2.JPG" < "toy-01.jpg" — katta harflar kichiklardan oldin saralanadi (Unicode tartibi).
3-mashq (qiyin): eski zaxiralarni tozalash
ochiriladiganlar(nomlar, bugun, kun) funksiyasini yozing: kesh-YYYY-MM-DD ko'rinishidagi nomlardan kun kundan eskilarini qaytarsin. Boshqa nomlarga (masalan README.txt, kesh-xato) tegmasin. Sinov: bugun 2026-10-23, 7 kun, nomlar kesh-2026-10-23, kesh-2026-10-16, kesh-2026-10-15, kesh-2026-09-30, kesh-xato, README.txt. Yordam: /^kesh-(\d{4}-\d{2}-\d{2})$/ va Date farqi millisekundlarda (Date va vaqt zonalari).
Yechim
const KUN_MS = 24 * 60 * 60 * 1000;
function ochiriladiganlar(nomlar, bugun, kun) {
const boshi = new Date(`${bugun}T00:00:00Z`).getTime();
const chegara = boshi - kun * KUN_MS;
return nomlar.filter((nom) => {
const m = /^kesh-(\d{4}-\d{2}-\d{2})$/.exec(nom);
if (!m) return false; // bizning zaxira emas — tegmaymiz
return new Date(`${m[1]}T00:00:00Z`).getTime() < chegara;
});
}
const nomlar = [
"kesh-2026-10-23",
"kesh-2026-10-16",
"kesh-2026-10-15",
"kesh-2026-09-30",
"kesh-xato",
"README.txt",
];
console.log(ochiriladiganlar(nomlar, "2026-10-23", 7));Konsolda:
[ 'kesh-2026-10-15', 'kesh-2026-09-30' ]kesh-2026-10-16 — aynan 7 kun oldin, qoladi (<, <= emas). Chegarani qaysi tomonga qo'yish — kelishuv; muhimi uni test bilan qotirish. Eng muhim qator — if (!m) return false: o'chirish skripti faqat o'zi yaratgan narsaga tegsin. Sanalarni UTC'da (Z) hisobladik — vaqt mintaqasi va yozgi vaqt o'tishi kunni siljitmasin.
4-mashq: CLI qadami — paket:tekshir
valyuta loyihangizga scripts/paket-tekshir.mjs ni qo'shing (paket nomingiz @login/valyuta bo'lsa, paket.bin dagi kalit valyuta qoladi). package.json ga ikki skriptni va ESLint tuzatishini kiriting. Keyin ataylab buzing: package.json dagi "files" ga "src" qo'shing va npm run paket:tekshir ni ishga tushiring. Natijani ko'rib, qaytaring. Commit qilmang — u keyingi darslarda.
Yechim
Buzilgan holatda skript har src/*.ts fayli uchun xato qatorini stderr'ga chiqaradi: XATO: paketga tushmasligi kerak: src/…. Keyin exit 1 bilan tugaydi; sarlavha qatorida fayl soni va hajm ham oshadi. "files" ni qaytargandan keyin — …: 61 fayl, 29.4 kB … Paket tayyor. (sizdagi raqam README matningizga qarab biroz farq qiladi). Agar npm orqali ishga tushiring xatosi chiqsa — skriptni node scripts/… bilan to'g'ridan chaqirdingiz: npm_execpath faqat npm run ichida bor.
8. Real ishda
- Monorepolar va kutubxonalar: React, Vite, Next.js repolarida
scripts/papkasi — nashr, changelog, versiya oshirish skriptlari, deyarli hammasi Node'da. - CI: GitHub Actions qadamlari ko'pincha
node scripts/…mjs— bitta skript lokal va CI'da bir xil. - DevOps: zaxira, log tozalash, sertifikat yangilash — cron/systemd timer orqali.
- Intervyu: "Kross-platforma skriptni qanday yozasiz?" —
path.join,process.execPath,fsAPI'lari,.cmdtuzog'i va idempotentlik haqida gapira olsangiz, tajribali dasturchi ekaningiz ko'rinadi.
Xulosa
- Node skripti — Windows, macOS va Linux'da bir xil; bash'dan xavfsizroq va sinash oson.
- Windows'da
npm—npm.cmd:execFilebilanENOENT/EINVAL; yechimprocess.execPath+npm_execpathyoki execa. - zx qulay, lekin bash talab qiladi; Git Bash'siz Windows'da WSL xatosi,
usePowerShell()— boshqa sintaksis. fs.glob,fs.cp,rename,rm— o'rnatilgan; glob Windows'da katta-kichik harfni farqlamaydi, tartibni va'da qilmaydi.- Yaxshi skript: idempotent, quruq ishga tushirish rejimi bor, xatoda exit 1.
valyuta:scripts/paket-tekshir.mjs+prepublishOnly—61 fayl, 29.4 kB … Paket tayyor.
Keyingi dars: Web scraping Node'da — sahifadan ma'lumot olish: cheerio, robots.txt, tezlik cheklovi va huquqiy chegaralar.
Manbalar
- Node.js hujjati —
fs.glob,fs.cp: https://nodejs.org/api/fs.html - Node.js hujjati — child_process, Windows'da
.bat/.cmd: https://nodejs.org/api/child_process.html#spawning-bat-and-cmd-files-on-windows - execa: https://github.com/sindresorhus/execa
- zx: https://google.github.io/zx/
- npm hujjati — scripts (
prepublishOnly,npm_execpath): https://docs.npmjs.com/cli/v11/using-npm/scripts
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!