שרשור תנאים בבאש

שרשור תנאים בבאש

איך אני משרשר תנאים בבאש?
ניסיתי
קוד:
 griveDir=$(find /media/${USER} -type d -name ".appdata")

if ( chckPPA "grive" ) ; then
		if [ ! -d ${griveDir}/grive ] || [ ! -L ~/grive ]; then
			if ( ! -d ~/grive ); then
				mkdir "${griveDir}/grive"
				ln -s "${griveDir}" ~/grive
			else
				mv ~/grive "${griveDir}"
				ln -s "${griveDir}" ~/grive
			fi
	fi
		cd ~/grive
fi
ואני מקבל שגיאה
./installs2.sh: line 64: -d: command not found​
תודה למשיבים
 

BravoMan

Active member
הבעיה שלך אינה שרשור

הבעיה שלך היא שימוש ב d- בתוך סוגריים עגולים.
&nbsp
BASH לא מתנהג כמו C או שפות דומות.
אתה לא אמור לעטוף את התנאי אחורי if בסוגריים עגולים.
&nbsp
גם סוגריים מרובעים [ ] הם לא באמת סוגריים, הסוגר הפותח הוא למעשה פקודה במערכת, קובץ ריצה בשם ].
הוא זה שיודע לפרש פרמטרים כמו d- ויתר פרמטרי שורת פקודה שבאים אחרי השם שלו.
 
עכשיו כבר הסתבכתי

מה שמצאתי כגון באתר זה שפקודת if באה עם סוגריים מרובעים. ורק פקודת test ללא סוגריים.
ניסיתי כמה אפשרויות של סוגריים.
1. זוג סוגריים מרובעים
2. 2 זוגות
ועוד כל מיני קומבינות עם סוגריים עגולים.

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

BravoMan

Active member
סוגריים מרובעים ו-test זה אותו דבר

if מריץ את הפקודה שבאה אחריו, ופועל לפי מה שהיא מחזירה.
פקודה test מבצעת בדיקה לפי פרמטרים שאתה נותן לה.
פקודה ] עושה את אותו הדבר.
&nbsp
ב-BASH יש אופרטורים כגון && ו-|| שבעזרתם ניתן לשרשר כמה פקודות, ואז ה-if יפעל לפי התוצאה של האחרונה.
&nbsp
אם תסביר בצורה ברורה מה התנאי שאתה רוצה לכתוב - מה הבדיקה שאתה מעוניין לבצע, אוכל להסביר לך איך עושים.
 
עליתי על הטעות שלי

הבעיה התחילה בתנאי הראשון
if [ chckPPA "grive" ]; then
שבו שלחתי את "grive" לבדיקה בפונקציה chckPPA הבודקת האם grive מותקן?
if [ $(chckPPA "grive") ]; then
במידה וארצה לפרמט את המכשף, אני משתדל מראש להציב בתיקיית הבית רק קישורים סימבולים, לכונן השני של 2TB. וכדי למנוע שגיאות בעתיד, אני מוודא מראש שלא קיימת ספריה או קישור סימבולי {שכחתי להוסיף בדיקת תקינות הקישור) בשם זה בתיקיית הבית. ובמידה והספריה קיימת, להעבירה למיקום הרצויי וליצור לינק סמבולי בתיקיית הבית.

בכל מקרה עדיין לא הסתיימו הצרות. והתעוררה בעייה חדשה בעקבות
griveDir=$(find /media/${USER} -type d -name ".appdata")
ואני מקבל רצף של שגיאות
find: ‘/media/owner/SCCARD/Music/תימנית/ציון גולן/אשורר שיר/USUSUSUS.usu’: Input/output error
אף כי הפלט של set -x
+ griveDir=/media/owner/DocWDC/Documents/.appdata
כנראה שתיקיית /media/owner/SCCARD/ הינו כרטיס הזיכרון של הסלולארי שאינו מעוגן. האם ישנה אפשרות להגביל את החיפוש שלא יחפש בכונני רשת?
 

BravoMan

Active member
אז ככה:

נתחיל מהתנאי הראשון:
אם chckPPA היא פונקציה בקסריפט שלך שמחזירה 0 כשהיא מצליחה (מוצאת את מה שרצית) ומספר אחר כשהיא נכשלת (לא מוצאת) או קובץ ריצה חיצוני עם exit code מתאים, את התנאי אתה צריך לרשום כך:
if chckPPA "grive"; then

אין צורך בסוגריים משום סוג, if יריץ ישירות את הפונקציה ויתייחס לתוצאה.

שים לב שהמבנה ()$ מחזיר את הפלט של מה שבתוכו במקום exit code, ו-] לא באמת סוגר אלא קובץ ריצה במערכת שלך שיודע לבצע בדיקות מאוד ספציפיות.

כשאתה רוצה לבדוק exit code של פונקציה או קובץ ריצה משלך ב-if, אתה לא צריך אף אחד מאלה!

אני מדגיש שוב שמבנה if של Bash שונה ממבנה if במשפחת C של השפות ואינו דורש שום סוגריים!

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

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

אם אתה רוצה פלט נקי של מה ש-find מצא, ולא רוצה לראות שגיאות, עליך פשוט לזרוק את ה-stderr שלו לפח, בצורה כזו:
griveDir=$(find /media/${USER} -type d -name ".appdata" 2>/dev/null)

בהצלחה!
 
מוזר, הבדיקה הצליחה חלקית גם ללא סוגריים

פלט של הקוד עם set -x
קוד:
if chckPPA "grive"; then
	if  ! -d "${griveDir}"/grive  ||  ! -L ~/grive ; then
		if  ! -d ~/grive ; then
			mkdir "${griveDir}/grive"
			ln -s "${griveDir}" ~/grive
		else
			mv ~/grive "${griveDir}"
			ln -s "${griveDir}" ~/grive
		fi
	fi
		cd ~/grive
		grive -a
fi
+ -d /media/owner/DocWDC/Documents/.appdata/grive
./installs.sh: line 67: -d: command not found
+ -d /home/owner/grive
./installs.sh: line 68: -d: command not found
+ mkdir /media/owner/DocWDC/Documents/.appdata/grive
mkdir: cannot create directory `/media/owner/DocWDC/Documents/.appdata/grive': File exists
+ ln -s /media/owner/DocWDC/Documents/.appdata /home/owner/grive
ln: failed to create symbolic link '/home/owner/grive/.appdata': File exists
כנראה למען שאשמור על השפיות, אשתדל לדבוק כמה שיותר אחר התחביר של שפת c. ודיי לי בזאת שאין בבאש סוגריים בשם הפונקציה עד שאני נוטה להתעלם שמדובר בפונקציה.
אגב, איך אני שולח את הפלט של grive -a שייפתח בדפדפן
+ grive -a
-----------------------
Please go to this URL and get an authentication code:

[URL]https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fdocs.google.com%2Ffeeds%2F+https%3A%2F%2Fdocs.googleusercontent.com%2F+https%3A%2F%2Fspreadsheets.google.com%2Ffeeds%2F&redirect_uri=urn:ietf[/URL]
-----------------------
Please input the authentication code here:

ויאשר אוטומטית עבורי, ויכניס לטרמינל את הפלט של הקוד שהתקבל?



 

BravoMan

Active member
נראה שהבעיה שלך היא שאתה מנסה לכתוב סקריפט

אבל מסרב ללמוד את התחביר של BASH.

הוא לא התחביר של שפת C!
אם תמשיך להתעלם מזה, לא תגיע רחוק.

הנה כמה תיקונים לסקריפט שלך:
קוד:
if chckPPA "grive"; then
	if [ ! -d "${griveDir}"/grive ]  || [ ! -L ~/grive ]; then
		if [ ! -d ~/grive ]; then
			mkdir "${griveDir}/grive"
			ln -s "${griveDir}" ~/grive
		else
			mv ~/grive "${griveDir}"
			ln -s "${griveDir}" ~/grive
		fi
	fi

	cd ~/grive
	grive -a
fi
אנסה להסביר שוב:
בניגוד לשפת C, פקודת if ב-BASH תמיד בודקת דבר אחד בלבד: ה-exit code של הפקודה האחרונה.
אם הוא 0, אז מתבצע מה שבתוך התנאי, אם הוא כל דבר אחר, אז לא.

if לא יודע לבדוק אם קיים קובץ, לא יודע לבדוק אם יש ספרייה, לא יודע לבדוק אם משהו הוא לינק סימבולי.

הוא לא מכרי את כל אלה.

מי כן מכיר?
שתי תוכנות: אחת שקוראים לה ] ואחרת שקוראים לה test.

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

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

אינך יכול לתפעל את הדפדפן מסקריפט כפי שביקשת כאן.
זה חורג הרבה מעבר ליכולות של BASH.

אם מדובר רק בשליחת בקשת GET עם פרמטרים וניתוח ה-HTML החוזר, בלי צורך באינטרקציה נוספת עם העמוד, אתה יכול להשתמש ב-wget או curl במקום הדפדפן.

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

אז לדעתי, כל שתוכל לעשות זה להריץ את הדפדפן שלך עם ה-URL מהסקריפט בעזרת הפקודה open, ואז לתת לסקריפט להמתין עם read כדי שהמשתש יכול להעתיק את התשובה שקיבל בדפדפן.
 
סוף סוף מישהו עשה לי סדר בדברים

עם כל הקושי לשנות תפיסות והרגלים, שיניתי את התסריט בהתאם לתסריט שלך. אך לא הצלחתי ללכוד את הURL מהפלט של grive -a ולשלוח אותו לדפדפן
ניסיתי
URL=$(grive -a | grep http://*)&& echo $URL
ואני מקבל מסך ריק
 

BravoMan

Active member
אתה יכול לתת פלט לדוגמה של grive?

במצב הנוכחי, יותר סביר שתקבל זבל, אם ה-URL לא לבד בשורה, מאשר שלא תקבל כלום, אבל צריך לראות מה מגיע ל-grep.
&nbsp
האם ה-URL בפלט הוא לבד בשורה, או שיש סביבו עוד דברים?
הכוכבית שם כפי שכתבת אותה מיותרת, כנראה כי היא שייכת ל-/, כלומר חפש דברים מהסוג //////:http
כנראה התכוונת להוסיף נקודה לפני הכוכבית כדי שהיא תתאים //:http ואז כל מיני.
 
ה url בשורה נפרדת

פלט ללא ה grep
קוד:
+ grive -a
-----------------------
Please go to this URL and get an authentication code:
 
[URL]https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fdocs.google.com%2Ffeeds%2F+https%3A%2F%2Fdocs.googleusercontent.com%2F+https%3A%2F%2Fspreadsheets.google.com%2Ffeeds%2F&redirect_uri=urn:ietf[/URL]
-----------------------
Please input the authentication code here:
עם ה-grep הוא ממתין לקוד. והפלט עם קשקוש
קוד:
++ grive -a
++ grep http://
gggggg
Failed to obtain auth token: HTTP 400, body: {
  "error" : "invalid_grant"
}
exception: /build/grive2-2Hxkkx/grive2-0.5.1/libgrive/src/protocol/OAuth2.cc(80): Throw in function void gr::OAuth2::Auth(const string&)
Dynamic exception type: boost::exception_detail::clone_impl<gr::OAuth2::AuthFailed>
[gr::expt::BacktraceTag*] = #0 0x578d79 grive gr::Exception::Exception()
#1 0x5651a7 grive gr::OAuth2::AuthFailed::AuthFailed()
#2 0x564271 grive gr::OAuth2::Auth(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
#3 0x50b576 grive Main(int, char**)
#4 0x50c1e9 grive main
#5 0x7f1debbca830 /lib/x86_64-linux-gnu/libc.so.6 __libc_start_main
#6 0x50a4b9 grive _start


+ URL=
+ echo
 

BravoMan

Active member
אני חושב שאני מתחיל להבין:

grive היא תוכנית אינטראקטיבית, כלומר כזו שממתינה לקלט, לא תוכל להריץ אותה עם grep כמו שאתה רוצה.
היא תוקעת לך את הסקריפט כשהיא ממתינה לקלט, ולכן grep לא רץ כמו שצריך.
&nbsp
מבט חטוף בקוד מראה שאין אופציה רק להציג URL.
כרגע, אין לי ראיון איך לפתור את העניין למעט להוסיף אופציה כזו לקוד של grive
 
למעלה