ארכיון יומי: 29 ינואר, 2010

למצוא את הקסם

בעולם הלינוקס, יוניקס והמאק יש פקודה אחת בשורת הפקודה שמאוד מאוד מקלה על החיים והרבה אנשים פשוט לא יודעים לעבוד איתה נכון.

הפקודה הפשוטה, הנחמדה והשימושית הזו נקראת find. מה שאני כותב כאן תקף ללינוקס אבל בד"כ גם אפשרי באותה צורה גם במערכות אחרות, אבל לפעמים עם פרמטרים וחוקים מעט שונים, בשביל תוצאה זהה.

אז איך עובדים עם find ? ובכן הצורה המופשטת ביותר היא פשוט לכתוב את הפקודה כמו שהיא, כך שהיא תחזיר לנו רשימה של כל הקבצים והספריות במקום הנוכחי שלנו:

$ find

במידה ונרצה לחפש במקום אחר, נעשה את זה בצורה הבאה:

$ find /some/path

והחיפוש יתבצע על כל הקבצים והספריות בנתיב מסויים.

במידה ונרצה לחפש בכמה נתיבים בייחד עם בסיס משותף נוכל לעשות את זה בצורה הבאה:

$ find /some/{path,location,directory}

ואז החיפוש יתבצע גם בתת הספרייה path, גם בlocation וגם ב directory. שימו לב שהסוגריים המסולסלים שייכים ל bash ולא ל find והם מפורשים עבור find ל3 נתיבים שונים. כלומר זה מקביל ל:

$ find /some/path /some/location /some/directory

ניתן ככה גם לחפש בכמה נתיבים שונים לגמרי, אבל כאשר הבסיס הוא אחיד, אני ממליץ על השיטה של הסוגריים המסולסלים שחוסכת לנו כתיבה.

נגיד ונרצה לחפש רק מבנה מסויים של קבצים, נגיד קבצים שיש בהם את הצירוף test:

$ find /some/path -name "*test*"

הסיבה לגרשיים היא בשביל ש bash לא ינסה לפרש את הכוכביות למשהו שקשור אליו (לפעמים יכול להיות מצב שכזה), אלא יעביר אותם כמו שהם אל התוכנה.

במידה ונרצה לחפש ספרייה או סוג מאוד מדוייק של קובץ (לפי מערכת הקבצים של לינוקס/יוניקס ולא לפי סיומת) נשתמש בפקודה הבאה:

$ find /some/path -type d

ונקבל את כל רשימת הספריות היושבות תחת נתיב מסויים.

במידה ונרצה אבל לקבל רק את הספריות תחת אותו נתיב ללא תת הספריות שיש להן, נוכל להגביל את find בצורה הבאה:

$ find /some/path -type d -maxdepth 1

ועכשיו יש לנו רק את הספריות תחת הנתיב שביקשנו. במידה ונרצה אבל לקבל את הספריות ברמה ה 2 אבל לא יותר מ5 רמות בתוכן, נעשה את זה בצורה הבאה:

$ find /some/path -type d -maxdepth 5 -mindepth 2

נגיד ונרצה לקבל רק קבצים ששונו במהלך ה24 שעות אחרונות ומעלה נעשה את זה בצורה הבאה:

$ find /some/path -mtime +0

חשוב להבין קצת איך הזמנים האלו עובדים.

mtime עובד על n*24 אבל חשוב להבין משהו חשוב: 0 הוא לא 24*0 אלא 0 אומר רק 24 שעות. כלומר אפשר להגיד שזה יותר כמות הפעמים שנעשה 24+24 . כך שהספרה 1 היא בעצם 48 שעות.

עוד משהו שחשוב לדעת זה שכאשר רושמים רק מספר ללא סימן, אנחנו אומרים לfind למצוא רק ב24 שעות הנוכחיות, בעוד שבמידה ונוסיף את הסימן פלוס לפני המספר, נגיד לו שמטווח של 24 שעות ומעלה. ואם זה יהיה עם מינוס, אז עד 24 שעות ומטה. ככה זה עם כל סוגי הזמנים (מבחינת לוגיקה, לא מבחינת כמות שעות), גם אם מדובר בשניות או דקות.

עוד פעולה שתעזור לכם מאוד, זו האפשרות להריץ פקודה על כל דבר שנמצא באמצעות find ואנחנו נעשה את זה באמצעות הפקודה exec :

$ find /some/path -exec /bin/rm -rf {} \;

חשוב לשים לב לכמה פרטים:

  • כמו בכל האפשרויות האחרות, אפשר לשלב את כולם בשורה אחת (אלא אם כתוב בתעוד משהו אחר בנושא על אפשרות כלשהי)
  • סוגריים מסולסלים הם שם הקובץ המלא שהתקבל והם לא שייכים ל bash אלא ל find
  • הלוכסן ההפוך עם הנקודה פסיק צריכים להיות עם רווח מהפקודה/סוגריים מסולסלים, אחרת find יצעק על שגיאה ב exec
  • במידה וצריך יותר מפקודה אחת, אז צריך להוסיף עוד אפשרות של exec בהתאם לכמות הפקודות שצריך לבצע. לפעמים צריך לשים אותם לפי סדר מסויים אם אחת תשפיע על השנייה
  • אי אפשר להשתמש בפקודות bash אלא רק בתוכנות ממשיות. אני ממליץ להשתמש בנתיב המלא לפקודה, אך במידה והפקודה נמצאת במשתנה PATH לא חייבים.

עוד משהו חשוב שלפעמים צריך זה להדפיס נתונים על כל קובץ. ניתן להדפיס את שם הקובץ והנתיב שלו עם האפשרות print:

$ find /some/path -print

במידה ויש רצון להדפיס פרמטרים ספציפיים כמו נתוני state על הקובץ, תאריכים שונים ועוד, אפשר להשתמש באפשרות printf

$ find /some/path -printf "…."

יש ל find עוד המון יכולות ואפשרויות מחיפוש באמצעות ביטויים רגולריים (regex) ועד לצורת הרשאות. יש פשוט המון אפשרויות שלא תמיד חשבתם עליהם אבל כשתדעו עליהם, פתאום תראו עד כמה הפקודה מקלה על צורת העבודה שלכם ולכן מומלץ להמשיך ולילמוד על האפשרויות של find במסמך ה man של הפקודה.