מעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה
-
אתה עדיין חושב שהבעיה היא רקורסיה.
אתה לא עובר על תיקיות אלא על בקשות אינטרנט.
הרקורסיה זה סה"כ מבנה להשיג את כל הנתיבים.
מה שלוקח לך את הזמן זה בקשת האינטרנט, זה לא משנה אם זה יהיה בלולאה או בפטיש ומסמר.
אתה צריך פשוט להתקדם צעד צעד, לשמור מצב, ולהתקדם.
נכון, זה לא פשוט, ואתה בטח תגיד שזה לא צודק/מובן וניסית ולא עבד. -
אתה עדיין חושב שהבעיה היא רקורסיה.
אתה לא עובר על תיקיות אלא על בקשות אינטרנט.
הרקורסיה זה סה"כ מבנה להשיג את כל הנתיבים.
מה שלוקח לך את הזמן זה בקשת האינטרנט, זה לא משנה אם זה יהיה בלולאה או בפטיש ומסמר.
אתה צריך פשוט להתקדם צעד צעד, לשמור מצב, ולהתקדם.
נכון, זה לא פשוט, ואתה בטח תגיד שזה לא צודק/מובן וניסית ולא עבד.@dovid אני לא חושב שהבעיה היא רקורסיה, אני בסה"כ מחפש דרך אחרת...
האמת שקשה לי לדמיין איך לעשות את זה עם רקורסיה, לבקש שיכתבו לי קוד - אני לא רוצה, אין לי זמן להשקיע בבנית אלגוריתם שגם ימדוד זמן, גם יבדוק שהמשאבים שהוא דורש לא חוצים את הרף של גוגל סקריפט (לא כ"כ נדיבים לפי מה שהבנתי, אולי אני טועה) וגם יתן לי לחזור לאותו מקום שבו הוא עצר תוך כדי שמירת מבנה הגיבוי (פשוט אותו מבנה שבו הוא נמצא שם - בשרת של ימות המשיח).למה לא פשוט למצוא דרך אחרת שיותר תתאים לי, בתור מתכנת מתחיל וחסר ידע וזמן?
גם המבנה הסופי של הגיבוי הוא בצורה מסוימת מסיבה מסוימת, ורקורסיה עם תחנות עצירה מאוד מקשים על זה, לפחות עד כמה שאני יודע.
לכן שאלתי שאלה פשוטה, בלי הנחות מקדימות ובלי שום דבר פשוט בקשת מידע, מה הדרך הנכונה.
-
אתה עדיין חושב שהבעיה היא רקורסיה.
אתה לא עובר על תיקיות אלא על בקשות אינטרנט.
הרקורסיה זה סה"כ מבנה להשיג את כל הנתיבים.
מה שלוקח לך את הזמן זה בקשת האינטרנט, זה לא משנה אם זה יהיה בלולאה או בפטיש ומסמר.
אתה צריך פשוט להתקדם צעד צעד, לשמור מצב, ולהתקדם.
נכון, זה לא פשוט, ואתה בטח תגיד שזה לא צודק/מובן וניסית ולא עבד.@dovid כתב במעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה:
אתה עדיין חושב שהבעיה היא רקורסיה.
אתה לא עובר על תיקיות אלא על בקשות אינטרנט.
הרקורסיה זה סה"כ מבנה להשיג את כל הנתיבים.
מה שלוקח לך את הזמן זה בקשת האינטרנט, זה לא משנה אם זה יהיה בלולאה או בפטיש ומסמר.
אתה צריך פשוט להתקדם צעד צעד, לשמור מצב, ולהתקדם.
נכון, זה לא פשוט, ואתה בטח תגיד שזה לא צודק/מובן וניסית ולא עבד.אם לדוגמא אשלח בקשה, אפתח תיקיה בדרייב בעלת אותו השם ואשמור את כל הנתיבים כך - נתיב בשרת, ID התיקיה.
אסיים את התיקיה הנ"ל ואתחיל תת תיקיה וכו'
ככה מסיימים תיקיה ועוברים הלאה, מציאת הנתיבים של כל הקבצים זה הרבה יותר מהיר מאשר הורדה שלהם, והרבה יותר קל להתחיל מחדש. ולאחר שיש לי רשימה מסודרת של נתיבים ואיפה הם אמורים להיות גם יותר קל להוריד אותם לאט לאט, אפשר אפילו להפעיל טריגרים בהפרדה של כמה שניות וככה לעשות את כל התהליך הרבה יותר מהר.אתה לא מסכים איתי? מי אמר שכאן רקורסיה + תחנות עצירה הם דוקא הפתרון הנכון?
-
אם מעניין אותך יש לי את הקוד הזה בnode.
שאני דבר ראשון מקבל את כל הנתיבים של הקבצים - שזה בקשות לא כבדות.
ואח"כ אני עובר על כל הקבצים עם מידע כמה אחוז כבר ירד (ושומר לקובץ ZIP את מה שנוצר)// ============================================ // ייבוא מודולים // ============================================ const axios = require('axios'); const fs = require('fs'); const path = require('path'); const archiver = require('archiver'); const TOKEN = "XX" const API_BASE_URL = 'https://www.call2all.co.il/ym/api/'; const ITEMS_PER_REQUEST = 500; // ============================================ // פונקציות עזר // ============================================ /** * יצירת תיקייה אם לא קיימת */ function ensureDir(dirPath) { if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath, { recursive: true }); } } /** * מחיקת תיקייה רקורסיבית */ function removeDir(dirPath) { if (fs.existsSync(dirPath)) { fs.rmSync(dirPath, { recursive: true, force: true }); } } /** * קבלת פרטי המערכת */ async function getSystemInfo() { try { const response = await axios.get(`${API_BASE_URL}GetSession`, { params: { token: TOKEN } }); if (response.data.responseStatus !== 'OK') { throw new Error(`Error getting system info: ${response.data.message}`); } return response.data; } catch (error) { console.error('❌ שגיאה בקבלת פרטי מערכת:', error.message); throw error; } } /** * קבלת תוכן תיקייה מהשרת */ async function getDirectoryContent(dirPath, filesFrom = 0, filesLimit = ITEMS_PER_REQUEST) { try { const response = await axios.get(`${API_BASE_URL}GetIVR2Dir`, { params: { token: TOKEN, path: dirPath, filesFrom, filesLimit } }); if (response.data.responseStatus !== 'OK') { throw new Error(`Error getting directory: ${response.data.message}`); } return response.data; } catch (error) { console.error(`❌ שגיאה בקבלת תוכן תיקייה ${dirPath}:`, error.message); throw error; } } /** * הורדת קובץ בודד */ async function downloadFile(filePath, localPath) { try { const response = await axios.get(`${API_BASE_URL}DownloadFile`, { params: { token: TOKEN, path: filePath }, responseType: 'arraybuffer' }); ensureDir(path.dirname(localPath)); fs.writeFileSync(localPath, response.data); return true; } catch (error) { console.error(`❌ שגיאה בהורדת קובץ ${filePath}:`, error.message); return false; } } /** * איסוף כל הקבצים מתיקייה (עם טיפול בפגינציה) - ללא הורדה */ async function collectFilesFromDir(dirPath) { let filesFrom = 0; let allFiles = []; let allIni = []; let allHtml = []; // איסוף כל הקבצים (עם פגינציה) while (true) { const dirContent = await getDirectoryContent(dirPath, filesFrom, ITEMS_PER_REQUEST); const currentFiles = dirContent.files || []; const currentIni = dirContent.ini || []; const currentHtml = dirContent.html || []; allFiles.push(...currentFiles); allIni.push(...currentIni); allHtml.push(...currentHtml); // אם קיבלנו פחות מהלימיט, זה אומר שזה הסיבוב האחרון if (currentFiles.length < ITEMS_PER_REQUEST) { break; } filesFrom += ITEMS_PER_REQUEST; } return [ ...allFiles, ...allIni, ...allHtml ]; } /** * סריקה רקורסיבית של כל התיקיות - רק איסוף נתיבים */ async function scanRecursively(dirPath, localDirPath, filesList = []) { // איסוף הקבצים מהתיקייה הנוכחית const files = await collectFilesFromDir(dirPath); // הוספת הקבצים למערך עם הנתיב המקומי for (const file of files) { filesList.push({ remotePath: file.what, localPath: path.join(localDirPath, file.name), name: file.name, size: file.size || 0 }); } // קבלת רשימת התיקיות const dirContent = await getDirectoryContent(dirPath, 0, ITEMS_PER_REQUEST); const dirs = dirContent.dirs || []; // עיבוד כל תיקייה באופן רקורסיבי for (const dir of dirs) { const subDirPath = dir.what; const localSubDirPath = path.join(localDirPath, dir.name); await scanRecursively(subDirPath, localSubDirPath, filesList); } return filesList; } /** * הורדת כל הקבצים עם התקדמות */ async function downloadAllFiles(filesList, concurrency = 10) { let completed = 0; const total = filesList.length; const startTime = Date.now(); console.log(`\n⬇️ מתחיל הורדת ${total} קבצים...\n`); // חלוקה לבאצ'ים להורדה מקבילית מבוקרת for (let i = 0; i < filesList.length; i += concurrency) { const batch = filesList.slice(i, i + concurrency); const downloadPromises = batch.map(async (file) => { const success = await downloadFile(file.remotePath, file.localPath); completed++; const percentage = Math.floor((completed / total) * 100); const elapsed = ((Date.now() - startTime) / 1000).toFixed(0); const estimatedTotal = total > 0 ? ((elapsed / completed) * total).toFixed(0) : 0; const remaining = estimatedTotal - elapsed; // עדכון progress bar const barLength = 30; const filled = Math.floor((completed / total) * barLength); const bar = '█'.repeat(filled) + '░'.repeat(barLength - filled); process.stdout.write(`\r[${completed}/${total}] ${bar} ${percentage}% | ${elapsed}s / ~${estimatedTotal}s`); return success; }); await Promise.all(downloadPromises); } console.log('\n'); return completed; } /** * יצירת קובץ ZIP */ async function createZip(sourceDir, outputPath) { return new Promise((resolve, reject) => { const output = fs.createWriteStream(outputPath); const archive = archiver('zip', { zlib: { level: 9 } // דחיסה מקסימלית }); output.on('close', () => { console.log(`\n📦 קובץ ZIP נוצר: ${outputPath}`); console.log(` גודל: ${(archive.pointer() / 1024 / 1024).toFixed(2)} MB`); resolve(); }); archive.on('error', (err) => { reject(err); }); archive.pipe(output); archive.directory(sourceDir, false); archive.finalize(); }); } /** * פונקציה ראשית */ async function main() { console.log('🚀 מתחיל תהליך גיבוי...\n'); // בדיקת טוקן if (TOKEN === 'your-token-here') { console.error('❌ שגיאה: לא הוגדר טוקן! הדבק את הטוקן שלך בתחילת הקובץ.'); process.exit(1); } const startTime = Date.now(); const startDate = new Date(); // יצירת פורמט תאריך מלא const year = startDate.getFullYear(); const month = String(startDate.getMonth() + 1).padStart(2, '0'); const day = String(startDate.getDate()).padStart(2, '0'); const hours = String(startDate.getHours()).padStart(2, '0'); const minutes = String(startDate.getMinutes()).padStart(2, '0'); const seconds = String(startDate.getSeconds()).padStart(2, '0'); const dateTimeStr = `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`; try { // קבלת פרטי מערכת console.log('📋 מקבל פרטי מערכת...'); const systemInfo = await getSystemInfo(); const systemNumber = systemInfo.username || 'unknown'; console.log(` מערכת: ${systemNumber}`); console.log(` שם: ${systemInfo.name || 'N/A'}\n`); // יצירת תיקייה זמנית עם אותו שם כמו הקובץ const backupName = `backup_${systemNumber}_${dateTimeStr}`; const TEMP_DIR = path.join(__dirname, `temp_${backupName}`); console.log('📁 יוצר תיקייה זמנית...'); ensureDir(TEMP_DIR); // שלב 1: סריקה ואיסוף נתיבים console.log('🔍 שלב 1: סורק תיקיות ואוסף רשימת קבצים...\n'); const allFiles = await scanRecursively('ivr2:/', TEMP_DIR); const totalSize = allFiles.reduce((sum, file) => sum + (file.size || 0), 0); const totalSizeMB = (totalSize / 1024 / 1024).toFixed(2); console.log(`\n✅ סריקה הושלמה!`); console.log(` 📊 נמצאו: ${allFiles.length} קבצים`); console.log(` 💾 גודל כולל: ${totalSizeMB} MB\n`); // שלב 2: הורדת קבצים console.log('⬇️ שלב 2: מוריד קבצים...'); const successCount = await downloadAllFiles(allFiles, 10); console.log(`✅ הורדה הושלמה: ${successCount}/${allFiles.length} קבצים\n`); // יצירת קובץ ZIP const zipPath = path.join(__dirname, `${backupName}.zip`); console.log('\n📦 יוצר קובץ ZIP...'); await createZip(TEMP_DIR, zipPath); // מחיקת תיקייה זמנית console.log('🧹 מנקה תיקייה זמנית...'); removeDir(TEMP_DIR); const duration = ((Date.now() - startTime) / 1000 / 60).toFixed(2); console.log(`\n✅ הגיבוי הושלם בהצלחה!`); console.log(`⏱️ זמן כולל: ${duration} דקות`); console.log(`📁 קובץ הגיבוי: ${zipPath}`); } catch (error) { console.error('\n❌ שגיאה בתהליך הגיבוי:', error.message); // ניקוי במקרה של שגיאה if (TEMP_DIR) { console.log('🧹 מנקה תיקייה זמנית...'); removeDir(TEMP_DIR); } process.exit(1); } } // הרצת התוכנית if (require.main === module) { main(); }שים לב שצריך להתקין את הספריות ולכתוב טוקן.
-
אם מעניין אותך יש לי את הקוד הזה בnode.
שאני דבר ראשון מקבל את כל הנתיבים של הקבצים - שזה בקשות לא כבדות.
ואח"כ אני עובר על כל הקבצים עם מידע כמה אחוז כבר ירד (ושומר לקובץ ZIP את מה שנוצר)// ============================================ // ייבוא מודולים // ============================================ const axios = require('axios'); const fs = require('fs'); const path = require('path'); const archiver = require('archiver'); const TOKEN = "XX" const API_BASE_URL = 'https://www.call2all.co.il/ym/api/'; const ITEMS_PER_REQUEST = 500; // ============================================ // פונקציות עזר // ============================================ /** * יצירת תיקייה אם לא קיימת */ function ensureDir(dirPath) { if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath, { recursive: true }); } } /** * מחיקת תיקייה רקורסיבית */ function removeDir(dirPath) { if (fs.existsSync(dirPath)) { fs.rmSync(dirPath, { recursive: true, force: true }); } } /** * קבלת פרטי המערכת */ async function getSystemInfo() { try { const response = await axios.get(`${API_BASE_URL}GetSession`, { params: { token: TOKEN } }); if (response.data.responseStatus !== 'OK') { throw new Error(`Error getting system info: ${response.data.message}`); } return response.data; } catch (error) { console.error('❌ שגיאה בקבלת פרטי מערכת:', error.message); throw error; } } /** * קבלת תוכן תיקייה מהשרת */ async function getDirectoryContent(dirPath, filesFrom = 0, filesLimit = ITEMS_PER_REQUEST) { try { const response = await axios.get(`${API_BASE_URL}GetIVR2Dir`, { params: { token: TOKEN, path: dirPath, filesFrom, filesLimit } }); if (response.data.responseStatus !== 'OK') { throw new Error(`Error getting directory: ${response.data.message}`); } return response.data; } catch (error) { console.error(`❌ שגיאה בקבלת תוכן תיקייה ${dirPath}:`, error.message); throw error; } } /** * הורדת קובץ בודד */ async function downloadFile(filePath, localPath) { try { const response = await axios.get(`${API_BASE_URL}DownloadFile`, { params: { token: TOKEN, path: filePath }, responseType: 'arraybuffer' }); ensureDir(path.dirname(localPath)); fs.writeFileSync(localPath, response.data); return true; } catch (error) { console.error(`❌ שגיאה בהורדת קובץ ${filePath}:`, error.message); return false; } } /** * איסוף כל הקבצים מתיקייה (עם טיפול בפגינציה) - ללא הורדה */ async function collectFilesFromDir(dirPath) { let filesFrom = 0; let allFiles = []; let allIni = []; let allHtml = []; // איסוף כל הקבצים (עם פגינציה) while (true) { const dirContent = await getDirectoryContent(dirPath, filesFrom, ITEMS_PER_REQUEST); const currentFiles = dirContent.files || []; const currentIni = dirContent.ini || []; const currentHtml = dirContent.html || []; allFiles.push(...currentFiles); allIni.push(...currentIni); allHtml.push(...currentHtml); // אם קיבלנו פחות מהלימיט, זה אומר שזה הסיבוב האחרון if (currentFiles.length < ITEMS_PER_REQUEST) { break; } filesFrom += ITEMS_PER_REQUEST; } return [ ...allFiles, ...allIni, ...allHtml ]; } /** * סריקה רקורסיבית של כל התיקיות - רק איסוף נתיבים */ async function scanRecursively(dirPath, localDirPath, filesList = []) { // איסוף הקבצים מהתיקייה הנוכחית const files = await collectFilesFromDir(dirPath); // הוספת הקבצים למערך עם הנתיב המקומי for (const file of files) { filesList.push({ remotePath: file.what, localPath: path.join(localDirPath, file.name), name: file.name, size: file.size || 0 }); } // קבלת רשימת התיקיות const dirContent = await getDirectoryContent(dirPath, 0, ITEMS_PER_REQUEST); const dirs = dirContent.dirs || []; // עיבוד כל תיקייה באופן רקורסיבי for (const dir of dirs) { const subDirPath = dir.what; const localSubDirPath = path.join(localDirPath, dir.name); await scanRecursively(subDirPath, localSubDirPath, filesList); } return filesList; } /** * הורדת כל הקבצים עם התקדמות */ async function downloadAllFiles(filesList, concurrency = 10) { let completed = 0; const total = filesList.length; const startTime = Date.now(); console.log(`\n⬇️ מתחיל הורדת ${total} קבצים...\n`); // חלוקה לבאצ'ים להורדה מקבילית מבוקרת for (let i = 0; i < filesList.length; i += concurrency) { const batch = filesList.slice(i, i + concurrency); const downloadPromises = batch.map(async (file) => { const success = await downloadFile(file.remotePath, file.localPath); completed++; const percentage = Math.floor((completed / total) * 100); const elapsed = ((Date.now() - startTime) / 1000).toFixed(0); const estimatedTotal = total > 0 ? ((elapsed / completed) * total).toFixed(0) : 0; const remaining = estimatedTotal - elapsed; // עדכון progress bar const barLength = 30; const filled = Math.floor((completed / total) * barLength); const bar = '█'.repeat(filled) + '░'.repeat(barLength - filled); process.stdout.write(`\r[${completed}/${total}] ${bar} ${percentage}% | ${elapsed}s / ~${estimatedTotal}s`); return success; }); await Promise.all(downloadPromises); } console.log('\n'); return completed; } /** * יצירת קובץ ZIP */ async function createZip(sourceDir, outputPath) { return new Promise((resolve, reject) => { const output = fs.createWriteStream(outputPath); const archive = archiver('zip', { zlib: { level: 9 } // דחיסה מקסימלית }); output.on('close', () => { console.log(`\n📦 קובץ ZIP נוצר: ${outputPath}`); console.log(` גודל: ${(archive.pointer() / 1024 / 1024).toFixed(2)} MB`); resolve(); }); archive.on('error', (err) => { reject(err); }); archive.pipe(output); archive.directory(sourceDir, false); archive.finalize(); }); } /** * פונקציה ראשית */ async function main() { console.log('🚀 מתחיל תהליך גיבוי...\n'); // בדיקת טוקן if (TOKEN === 'your-token-here') { console.error('❌ שגיאה: לא הוגדר טוקן! הדבק את הטוקן שלך בתחילת הקובץ.'); process.exit(1); } const startTime = Date.now(); const startDate = new Date(); // יצירת פורמט תאריך מלא const year = startDate.getFullYear(); const month = String(startDate.getMonth() + 1).padStart(2, '0'); const day = String(startDate.getDate()).padStart(2, '0'); const hours = String(startDate.getHours()).padStart(2, '0'); const minutes = String(startDate.getMinutes()).padStart(2, '0'); const seconds = String(startDate.getSeconds()).padStart(2, '0'); const dateTimeStr = `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`; try { // קבלת פרטי מערכת console.log('📋 מקבל פרטי מערכת...'); const systemInfo = await getSystemInfo(); const systemNumber = systemInfo.username || 'unknown'; console.log(` מערכת: ${systemNumber}`); console.log(` שם: ${systemInfo.name || 'N/A'}\n`); // יצירת תיקייה זמנית עם אותו שם כמו הקובץ const backupName = `backup_${systemNumber}_${dateTimeStr}`; const TEMP_DIR = path.join(__dirname, `temp_${backupName}`); console.log('📁 יוצר תיקייה זמנית...'); ensureDir(TEMP_DIR); // שלב 1: סריקה ואיסוף נתיבים console.log('🔍 שלב 1: סורק תיקיות ואוסף רשימת קבצים...\n'); const allFiles = await scanRecursively('ivr2:/', TEMP_DIR); const totalSize = allFiles.reduce((sum, file) => sum + (file.size || 0), 0); const totalSizeMB = (totalSize / 1024 / 1024).toFixed(2); console.log(`\n✅ סריקה הושלמה!`); console.log(` 📊 נמצאו: ${allFiles.length} קבצים`); console.log(` 💾 גודל כולל: ${totalSizeMB} MB\n`); // שלב 2: הורדת קבצים console.log('⬇️ שלב 2: מוריד קבצים...'); const successCount = await downloadAllFiles(allFiles, 10); console.log(`✅ הורדה הושלמה: ${successCount}/${allFiles.length} קבצים\n`); // יצירת קובץ ZIP const zipPath = path.join(__dirname, `${backupName}.zip`); console.log('\n📦 יוצר קובץ ZIP...'); await createZip(TEMP_DIR, zipPath); // מחיקת תיקייה זמנית console.log('🧹 מנקה תיקייה זמנית...'); removeDir(TEMP_DIR); const duration = ((Date.now() - startTime) / 1000 / 60).toFixed(2); console.log(`\n✅ הגיבוי הושלם בהצלחה!`); console.log(`⏱️ זמן כולל: ${duration} דקות`); console.log(`📁 קובץ הגיבוי: ${zipPath}`); } catch (error) { console.error('\n❌ שגיאה בתהליך הגיבוי:', error.message); // ניקוי במקרה של שגיאה if (TEMP_DIR) { console.log('🧹 מנקה תיקייה זמנית...'); removeDir(TEMP_DIR); } process.exit(1); } } // הרצת התוכנית if (require.main === module) { main(); }שים לב שצריך להתקין את הספריות ולכתוב טוקן.
@יהודי-טוב תודה, אבל אני צריך יותר "תוכנית עבודה", אני אמור לכתוב את זה בגוגל סקריפט, ושם יש הגבלה של 6 דקות, לכן חשוב לי שתהיה אפשרות לעצור ולהמשיך.
-
@יהודי-טוב תודה, אבל אני צריך יותר "תוכנית עבודה", אני אמור לכתוב את זה בגוגל סקריפט, ושם יש הגבלה של 6 דקות, לכן חשוב לי שתהיה אפשרות לעצור ולהמשיך.
@eido
לפעמים צריך לחשוב איך אתה כבן אדם היית עושה כזה דבר לו יצוייר שיש לך רק 6 דקות ביום לעשות את זה,
לאחר מכן תוכל לחשוב איך לכתוב את זה בקוד.לדוגמא במקרה כזה אני חושב שאני הייתי כותב כל יום בדף עד איפה כבר עברתי ואיפה אני אוחז כך שאוכל להמשיך למחרת באותו מיקום שעצרתי, מה דעתך?
-
@יהודי-טוב תודה, אבל אני צריך יותר "תוכנית עבודה", אני אמור לכתוב את זה בגוגל סקריפט, ושם יש הגבלה של 6 דקות, לכן חשוב לי שתהיה אפשרות לעצור ולהמשיך.
@eido כתב במעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה:
אני צריך יותר "תוכנית עבודה"
אולי תעשה משהו בסגנון שמבצע ריצה כדי לקבל את כל הנתיבים של הקבצים.
ותשמור את זה כJSON בגוגל שיטס ששם תיצור נניח שורה לכל תהליך שרץ ובשמירה תפצל את הJSON לפי מספר קבצים או גודל קבצים - לכמה תאים בשורה של התהליך...ואז תבצע תהליך כשכל תהליך מוריד את הקבצים בJSON של תא מסוים ובסיום קורא לאנדפוינט שמתקדם לתא הבא וכן הלאה..
-
@dovid הביא לך את דרך המלך, אתה משתמש ברקורסיה רק בשביל להשיג את רשימת הנתיבים, אחרי שיש לך אותם במערך, כל מה שאתה צריך לשמור זה את המערך ומספר שמייצג עד איפה הגעת.
אם אתה לא מוכן לכתוב קוד רקורסיבי אז תבקש מchatgpt לכתוב לך, זו הדרך הכי קלה, אני בכלל לא יכול לחשוב איך קוד איטרטיבי יהיה אלגוריתמית פשוט יותר מאשר רקורסיבי, הוא יהיה חייב להיות בנוי בצורה יוצאת דופן ולא טריוויאלית בכלל. -
@eido
לפעמים צריך לחשוב איך אתה כבן אדם היית עושה כזה דבר לו יצוייר שיש לך רק 6 דקות ביום לעשות את זה,
לאחר מכן תוכל לחשוב איך לכתוב את זה בקוד.לדוגמא במקרה כזה אני חושב שאני הייתי כותב כל יום בדף עד איפה כבר עברתי ואיפה אני אוחז כך שאוכל להמשיך למחרת באותו מיקום שעצרתי, מה דעתך?
@ivrtikshoret 100% הבעיה שלי היא לתרגם את זה לאלגוריתם יעיל.
-
@dovid הביא לך את דרך המלך, אתה משתמש ברקורסיה רק בשביל להשיג את רשימת הנתיבים, אחרי שיש לך אותם במערך, כל מה שאתה צריך לשמור זה את המערך ומספר שמייצג עד איפה הגעת.
אם אתה לא מוכן לכתוב קוד רקורסיבי אז תבקש מchatgpt לכתוב לך, זו הדרך הכי קלה, אני בכלל לא יכול לחשוב איך קוד איטרטיבי יהיה אלגוריתמית פשוט יותר מאשר רקורסיבי, הוא יהיה חייב להיות בנוי בצורה יוצאת דופן ולא טריוויאלית בכלל. -
@eido כתב במעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה:
אני צריך יותר "תוכנית עבודה"
אולי תעשה משהו בסגנון שמבצע ריצה כדי לקבל את כל הנתיבים של הקבצים.
ותשמור את זה כJSON בגוגל שיטס ששם תיצור נניח שורה לכל תהליך שרץ ובשמירה תפצל את הJSON לפי מספר קבצים או גודל קבצים - לכמה תאים בשורה של התהליך...ואז תבצע תהליך כשכל תהליך מוריד את הקבצים בJSON של תא מסוים ובסיום קורא לאנדפוינט שמתקדם לתא הבא וכן הלאה..
@יהודי-טוב כתב במעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה:
@eido כתב במעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה:
אני צריך יותר "תוכנית עבודה"
אולי תעשה משהו בסגנון שמבצע ריצה כדי לקבל את כל הנתיבים של הקבצים.
ותשמור את זה כJSON בגוגל שיטס ששם תיצור נניח שורה לכל תהליך שרץ ובשמירה תפצל את הJSON לפי מספר קבצים או גודל קבצים - לכמה תאים בשורה של התהליך...ואז תבצע תהליך כשכל תהליך מוריד את הקבצים בJSON של תא מסוים ובסיום קורא לאנדפוינט שמתקדם לתא הבא וכן הלאה..
זה מה שאני כרגע באמצע לעשות, ואנ יכאן בשביל למצוא את הדרך הנכונה
-
אולי כדאי להפריד תהליכים...
תהליך ראשי, רץ על ימות עצמם ואוסף דאטה
תהליכים משניים מעבדים את הדאטה שצריך להוריד, לשמור, ולעדכן את המרכזי שהם סיימו ויכולים לקבל עבודה נוספת.
את התיכים המשניים אתה יכול לשכפל ולהריץ גם 10 כאלה, ותקבל כח עיבוד של 10 סקריפטים, עם כעין שרת מרכזי שינהל את זה, ולא 1 צולע -
@dovid הביא לך את דרך המלך, אתה משתמש ברקורסיה רק בשביל להשיג את רשימת הנתיבים, אחרי שיש לך אותם במערך, כל מה שאתה צריך לשמור זה את המערך ומספר שמייצג עד איפה הגעת.
אם אתה לא מוכן לכתוב קוד רקורסיבי אז תבקש מchatgpt לכתוב לך, זו הדרך הכי קלה, אני בכלל לא יכול לחשוב איך קוד איטרטיבי יהיה אלגוריתמית פשוט יותר מאשר רקורסיבי, הוא יהיה חייב להיות בנוי בצורה יוצאת דופן ולא טריוויאלית בכלל. -
@חגי אתם נשמות טובות באמת, אבל אם ביקשתי לא רקורסיה, אז יש סיבה...
גם לזה, ה6 דקות לפעמים לא מספיקות, אני אומר מניסיון...
@eido כתב במעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה:
@חגי אתם נשמות טובות באמת, אבל אם ביקשתי לא רקורסיה, אז יש סיבה...
גם לזה, ה6 דקות לפעמים לא מספיקות, אני אומר מניסיון...
אני אומר לך שאם רקורסיה לא טובה מספיק בשבילך, אז שום דבר לא יהיה מספיק טוב בשבילך, הרקורסיה היא יעילה בזמן ריצה, החיסרון הלא מובהק שלה הוא שהיא צוברת זיכרון בשביל לזכור את הריצות הקודמות לפני שהיא מסיימת, אם לא נתקלת במגבלת זיכרון אלא במגבלת זמן, אז הבעיה שלך היא לא הרקורסיה.
@eido כתב במעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה:
אני מציע לכם לנסות פעם לכתוב קוד לארדואינו או esp8266, זה משנה חשיבה.
גם בארדואינו לעץ תיקיות בגודל שיכול להיכנס במחסנית הזיכרון גם הייתי ממליץ את זה, בארדואינו הבעיה שלך היא הפוכה, הזיכרון קטן וזמן הריצה בלתי מוגבל, זה בדיוק הפוך מהמקרה שלך.
-
@eido כתב במעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה:
@חגי אתם נשמות טובות באמת, אבל אם ביקשתי לא רקורסיה, אז יש סיבה...
גם לזה, ה6 דקות לפעמים לא מספיקות, אני אומר מניסיון...
אני אומר לך שאם רקורסיה לא טובה מספיק בשבילך, אז שום דבר לא יהיה מספיק טוב בשבילך, הרקורסיה היא יעילה בזמן ריצה, החיסרון הלא מובהק שלה הוא שהיא צוברת זיכרון בשביל לזכור את הריצות הקודמות לפני שהיא מסיימת, אם לא נתקלת במגבלת זיכרון אלא במגבלת זמן, אז הבעיה שלך היא לא הרקורסיה.
@eido כתב במעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה:
אני מציע לכם לנסות פעם לכתוב קוד לארדואינו או esp8266, זה משנה חשיבה.
גם בארדואינו לעץ תיקיות בגודל שיכול להיכנס במחסנית הזיכרון גם הייתי ממליץ את זה, בארדואינו הבעיה שלך היא הפוכה, הזיכרון קטן וזמן הריצה בלתי מוגבל, זה בדיוק הפוך מהמקרה שלך.
@חגי קודם כל, תודה.
יש גם מגבלת זכרון, פשוט אין לי קווים כ"כ גדולים בשביל לבדוק את זה, אבל אני רוצה לתת מענה גם להם.
אין ספק שרקורסיה זו שיטה מהירה, היא השיטה שאיתה התחלתי את הפרוייקט, הענין הוא שצריך לעצור כל פחות מ6 דקות ולהמשיך הלאה, כמו שאמרתי, אין לי את הידע והזמן בשביל לכתוב סקריפט שיעשה את זה, מבחינתי יותר קל לי לכתוב קוד אטרטיבי שיהיה אפשר לעצור ולהמשיך. והכל במבנה התיקיות שאני רוצה.נכון, בארדואינו הזכרון מוגבל מאוד וזמן ריצה, כולו שלך, אבל גם כאן הזכרון לא בידיים שלך. וכשמדובר על קו עם אלפי שלוחות ועוד יותר הרבה הודעות, בקלות מגיעים למכסות.
-
@חגי קודם כל, תודה.
יש גם מגבלת זכרון, פשוט אין לי קווים כ"כ גדולים בשביל לבדוק את זה, אבל אני רוצה לתת מענה גם להם.
אין ספק שרקורסיה זו שיטה מהירה, היא השיטה שאיתה התחלתי את הפרוייקט, הענין הוא שצריך לעצור כל פחות מ6 דקות ולהמשיך הלאה, כמו שאמרתי, אין לי את הידע והזמן בשביל לכתוב סקריפט שיעשה את זה, מבחינתי יותר קל לי לכתוב קוד אטרטיבי שיהיה אפשר לעצור ולהמשיך. והכל במבנה התיקיות שאני רוצה.נכון, בארדואינו הזכרון מוגבל מאוד וזמן ריצה, כולו שלך, אבל גם כאן הזכרון לא בידיים שלך. וכשמדובר על קו עם אלפי שלוחות ועוד יותר הרבה הודעות, בקלות מגיעים למכסות.
@eido כתב במעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה:
אטרטיבי שיהיה אפשר לעצור ולהמשיך. והכל במבנה התיקיות שאני רוצה.
לא קיים, אז אתה מתיאש מהפרוייקט או שאתה מנסה לשמור את המצב שלך איכשהו?
אם הרקורסיה לא נתנה לך מענה אז תהיה בטוח שקוד איטרטיבי יהיה פחות טוב מזה.יכול להיות שאני לא לגמרי מבין את הבעיה שלך, יש לך מבנה של כל התיקיות שאתה משיג עם רקורסיה, אני משער שעם עץ של אלפי תיקיות אתה משיג את רשימת כל הנתיבים תוך שניה וחצי לכל היותר, אז איפה אתה נתקע על 6 דקות?
בשלב שיש לך כבר רשימה של כל העץ תיקיות זה איטרטיבי לגמרי, תעשה עם הרשימה הזו מה שבא לך.
ואם אנחנו מדברים על מיליוני קבצים, אז אני לא רואה איך קוד איטרטיבי יעזור לך, הוא לא ימפה את הקבצים יותר מהר. -
@eido כתב במעבר על תיקיות ותתי תיקיות על כל קבציהן בלי רקורסיה:
אטרטיבי שיהיה אפשר לעצור ולהמשיך. והכל במבנה התיקיות שאני רוצה.
לא קיים, אז אתה מתיאש מהפרוייקט או שאתה מנסה לשמור את המצב שלך איכשהו?
אם הרקורסיה לא נתנה לך מענה אז תהיה בטוח שקוד איטרטיבי יהיה פחות טוב מזה.יכול להיות שאני לא לגמרי מבין את הבעיה שלך, יש לך מבנה של כל התיקיות שאתה משיג עם רקורסיה, אני משער שעם עץ של אלפי תיקיות אתה משיג את רשימת כל הנתיבים תוך שניה וחצי לכל היותר, אז איפה אתה נתקע על 6 דקות?
בשלב שיש לך כבר רשימה של כל העץ תיקיות זה איטרטיבי לגמרי, תעשה עם הרשימה הזו מה שבא לך.
ואם אנחנו מדברים על מיליוני קבצים, אז אני לא רואה איך קוד איטרטיבי יעזור לך, הוא לא ימפה את הקבצים יותר מהר.@חגי השגת הכתובות לוקחת הרבה זמן כי כל תיקיה זה שליחת בקשה חדשה והבקשות לוקחות זמן כמו שאמר dovid. מעבר לזה, המעבר על הקבצים בתיקיות ושמירתם ברשימה כלשהיא, גם כן לוקח זמן, זה בקלות עובר את ה6 דקות.
רקורסיה היתה מושלמת עד שגיליתי את מגבלת ה6 דקות, אז נוצר מצב שצריך להפסיק באמצע, וכאן אנחנו חוזרים לאותן הטענות כמו עד עכשיו...
רק להמחשה, עץ נתיבים של בערך 10 תיקיות עם קצת תת תיקיות ולא הרבה קבצים בתוכן לוקח קרוב ל5 דקות!
-
D dovid נעל נושא זה