הדרך הכי טובה להתעלם מתיקיה או קובץ עם find
הפקודה find היא אחת הפקודות הגמישות ביותר של יוניקס והיא יודעת למצוא קבצים לפי כל פרמטר שאפשר לדמיין. הרבה זמן תהיתי למה אין אף מתג שמאפשר ל find לדלג על ספריות בדומה ל --exclude
של grep. את התשובה מצאתי אחרי שהבנתי איך find עובד, והיא הרבה יותר פשוטה ממה שאתם מדמיינים.
אז בואו ניזכר רגע בהפעלה פשוטה של find למשל בשביל למצוא קבצים שהשם שלהם הוא package.json
:
$ find . -type f -name package.json
הפקודה find מקבלת רצף של קריטריונים לחיפוש ובונה מהם שרשרת תנאים. במקביל היא רצה על כל הקבצים והתיקיות החל מתיקיית ההתחלה שלה ומעבירה כל נתיב בשרשרת התנאים שמצאה. במקרה שלנו למשל שרשרת התנאים היא:
- אנחנו מחפשים קובץ
- השם חייב להיות package.json
כש find מוצא נתיב למשל demo.txt קודם כל הוא בודק מה סוג הדבר שיש שם. בואו נניח ש demo.txt הוא קובץ אז הוא יעבור את החוליה הראשונה וייפול בשניה.
שרשראות תנאים יכולות גם להתפצל, למשל ה find הבא שמשתמש ב or יזהה קבצים בשם package.json או תיקיות בשם node_modules
:
$ find . \( -type f -name package.json \) -or \( -type d -name node_modules \)
והנה עלינו לשתי שרשראות: או שעברת את כל השרשרת הראשונה, או שעברת את כל השרשרת השניה. כל שרשרת מורכבת משני תנאים.
עכשיו הגיע הזמן לשאול מה קורה עם הנתיב אחרי שהשרשרת נגמרת? באופן רגיל נתיב שסיים את כל השרשרת פשוט יודפס, אבל find נותנת לנו לשחק גם עם התנהגות זו. הפרמטר --exec
הוא דוגמא לפקודה שמסיימת את השרשרת, באמצעות הרצת פקודה על הקובץ שנמצא. זאת הסיבה שהשורה הבאה תמחק לכם קובץ בשם demo.txt למרות שאתם חושבים שאתם מדברים על תיקיה:
$ find . -name 'one.txt' -exec ls -l {} \; -type d
הבעיה היא שיצרנו שרשרת שמסתיימת ב exec ובזה הסיפור שלנו נגמר. הפקודה -type d
היא חסרת משמעות כאן כי היא באה אחרי סוף השרשרת.
ואם הבנתם את כל זה אתם מוכנים לשמוע את התשובה מתחילת הפוסט: משביל לדלג על קבצים או תיקיות ב find, כל מה שצריך זה לדאוג שהם לא יעברו את השרשרת. כך הפקודה הבאה תציג את כל הקבצים שמתחילים ב o ומסתיימים ב txt מלבד one.txt:
$ find . -type f -not -name 'one.txt' -name 'o*.txt'
ואם רוצים להתעלם מתיקיות הפקודה prune גורמת ל find לסיים את השרשרת ולדלג על התיקיה (היא רלוונטית רק כשהנתיב הוא תיקיה). לכן הפקודה הבאה תחפש את הקובץ package.json בכל מקום מלבד בתוך תיקיית node_modules
:
$ find . -type d -name node_modules -prune -false -or -name package.json
ברירת המחדל של -prune
היא להדפיס את התיקיה עליה היא דילגה, והתוספת -false
מיד אחריה מדלגת על אותה הדפסה. בלי זה נקבל בפלט גם את התיקיה node_modules
עליה דילגנו.