Linux shell glob

איך אני מציג רשימה של קבצים לדוגמא שמסתיימים ב .C גם כאשר אני לא נמצא בתיקייה עצמה

ושאלה נוספת יש לי את התייקיה

wildcards

ובתוכה 5 תיקיות כיצד אני מוחק מכל התיקיות את הקבצים שמסתיימים ב.png מבלי להיכנס לכל תיקייה ובפקודה אחת אם אפשרי וגם מבלי למחוק את התיקייה עצמה

תודה.

יש יותר מדרך אחת לעשות זאת. אתה אולי מכוון לשימוש ב-ls, אבל כדי להמשיך לשאלה השנייה, אציג פתרון אפשרי בעזרת הפקודה find (שגם בעזרתה יש יותר מדרך אחת להגיע לתוצאות שרצית).

בשתי הפקודות ה-glob כוכבית (*) יכול לשמש אותנו, כלומר: כוכבית נקודה האות c יחזיר את השמות המסתיימים כך.

אם יש לנו תיקייה בשם example ומתחתיה עץ תיקייות/קבצים כזה:

$ tree example/
example/
├── d0
│   ├── bar.c
│   ├── f0.png
│   ├── f1.png
│   └── f3.png
├── d1
│   ├── f0.png
│   └── f1.png
├── d2
│   └── f0.png
├── d3
│   └── f0.png
├── d4
│   └── f0.png
├── f0.png
└── foo.c

כלומר, תחת התיקייה המדוברת יש קובץ c וקובץ png, וגם 5 תתי-תיקיות שבכולן לפחות קובץ png אחד ובראשונה גם קובץ c.

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

לשאלתך הראשונה - כדי להציג קבצים בעלי תבנית שם מסויימת הנמצאים בתקייה מסויימת:

  • ארגומנט ראשון: הנתיב של התיקייה בה תרצה לאתר את הקבצים.
    [אם מחפש החל מהתקייה הנוכחית, אפשר להשמיט את הארגומנט, אבל עדיף להשאירו ולהשתמש בנקודה]
  • ארגומנט שני: האופציה name (לפני אופציות מצמידים מקף) ואחריה התבנית שמתאימה לשמות הקובץ הרצויים.
$ find example/ -name *.c
example/d0/bar.c
example/foo.c
  • אם נרצה להיות מדויקים יותר (כדאי כדי למנוע דברים לא צפווים) נוסיף את האופציה type עם הערך f כדי לקבל בתוצאות קבצים בלבד (ללא תקיות המתאימות לתבנית).
  • אם נרצה שהתבנית תתאים גם לאותיות קטנות וגם לגדולות (case insensitive) נשתמש באופציה iname ואז יוחזרו גם הקובץ file0.c וגם הקובץ FILE1.C
  • אם נרצה לקבל תצאות רק מהתקייה בה התחלנו לחפש (ולא לחפש בתתי התיקיות) נוסיף את האופציה maxdepth עם הערך 1. חשוב! האופציה הזו גלובלית וצריכה להופיע לפני האופציות האחרות.
$ find example/ -maxdepth 1 -iname *.c -type f
example/foo.c

לשאלתך השנייה - כדי למחוק מתתי-תיקיות קבצים בעלי תבנית שם מסויימת:

  • נשתמש באופציה delete
  • אם נרצה למחוק קבצים רק בתתי-תיקייות, ולא קבצים בתקייה ממנה מתחיל החיפוש, נוכל לשנות את הארגומנט הראשון ולהוסיף כוכבית לוכסן (Slash) כדי לסמן חיפוש בכל תתי-התיקיות ולא בתיקיית הבסיס שלהן.
find ./example/*/ -name *.png -type f -delete

זהירות! פעולות מחיקה פזיזות עלולות להוביל ל-:sob:
מומלץ לפני ביצוע פקודת המחיקה, להריץ פקודה דומה, שבמקום אפציין delete נשתמש באופציות print ו-depth שידפיסו את כל מה שעומד להימחק:
[depth היא אופציה גלובלית המופעלת בצורה מרומזת כשמשתמשים ב-delete]

$ find ./example/*/ -depth -name *.png -type f -print
./example/d0/f0.png
./example/d0/f3.png
./example/d0/f1.png
./example/d1/f0.png
./example/d1/f1.png
./example/d2/f0.png
./example/d3/f0.png
./example/d4/f0.png

אגב,גם כשמתשמישם ב-delete מומלץ להוסיף גם את האופציה print וכך יודפסו למסך הדברים שנמחקו.

בדוגמה שנתתי כאן, לאחר המחיקה, עץ הקבצים/תקיות יראה כך:

$ tree example/
example/
├── d0
│   └── bar.c
├── d1
├── d2
├── d3
├── d4
├── f0.png
└── foo.c

תודה רבה ניסיתי גם יש אפשרות לעשות מחיקה של כמה קבצים נגיד של .c אבל לעשות בתוך הפקודה שלא יימחק נגיד קובץ מסויים של .c