ฉันได้ลองเรียกคำสั่ง chmod ในลำดับที่ไม่ถูกต้อง chmod file.txt -rสิ่งนี้ทำงานได้ด้วยเหตุผลบางอย่าง chmod file.txt +rในทางกลับกันปฏิเสธที่จะทำงาน ทำไมนี้ ด้วยเหตุผลอะไรคำสั่งหนึ่งทำงานและอื่น ๆ ไม่ได้?
ฉันได้ลองเรียกคำสั่ง chmod ในลำดับที่ไม่ถูกต้อง chmod file.txt -rสิ่งนี้ทำงานได้ด้วยเหตุผลบางอย่าง chmod file.txt +rในทางกลับกันปฏิเสธที่จะทำงาน ทำไมนี้ ด้วยเหตุผลอะไรคำสั่งหนึ่งทำงานและอื่น ๆ ไม่ได้?
คำตอบ:
นี่เป็นสิ่งที่แปลกประหลาดของวิธีที่ GNU chmod จัดการกับอินพุตและไม่สามารถพกพาไปยังการใช้งาน chmod ที่ใช้ POSIX ได้ทั้งหมด
โปรดทราบว่าไวยากรณ์ของPOSIXchmod coomand-line ต้องการโหมดที่จะมาก่อนเช่นเดียวกับGNUchmod (ตัวเลือกควรมาก่อนโหมดด้วย) สิ่งอื่นใดก็คือการเล่นโวหารที่ไม่มีเอกสาร
ทีนี้ลองดูว่าทำไมมันถึงเกิดขึ้นในการติดตั้งแบบนี้
มันบอกเป็นนัยในคู่มือ :
แม้ว่าโดยทั่วไปแล้ว '
chmod a-w file' จะดีกว่าและchmod -w file(ถ้าไม่มี--) จะบ่นว่ามันทำงานแตกต่างจากสิ่งที่chmod a-w fileจะทำหรือไม่
สั้น ๆ , ตัวเลือกแยกวิเคราะห์โดยจะมีคำนำหน้าด้วยgetopt -เช่นเดียวกับในls -a, aเป็นตัวเลือก แบบยาวls --allมีallเป็นตัวเลือก rm -rf(เทียบเท่าrm -r -f) มีทั้งตัวเลือกrและf
ทุกสิ่งทุกอย่างเป็นอาร์กิวเมนต์ที่ไม่ใช่ตัวเลือกที่เรียกว่าในทางเทคนิคตัวถูกดำเนินการ ฉันชอบที่จะเรียกข้อโต้แย้งตำแหน่งเหล่านี้ตามความหมายของพวกเขาถูกกำหนดโดยตำแหน่งญาติ ในchmodอาร์กิวเมนต์ตำแหน่งแรกคือโหมดและอาร์กิวเมนต์ตำแหน่งที่สองคือชื่อไฟล์
-อย่างดีที่สุดโหมดไม่ควรนำไปด้วย ถ้าเป็นเช่นนั้นคุณควรใช้--ในการบังคับให้แจงเป็นตัวถูกดำเนินการแทนตัวเลือก (เช่นใช้chmod a-w fileหรือchmod -- -w fileแทนที่จะchmod -w fileเป็นเช่นนี้POSIX แนะนำด้วย
หากคุณดูซอร์สโค้ดคุณจะสังเกตเห็นว่ามันใช้getoptเพื่อแยกวิเคราะห์ตัวเลือกบรรทัดคำสั่ง ที่นี่มีการจัดการพิเศษสำหรับโหมด 'ไม่ถูกต้อง' เช่น-w:
case 'r':
case 'w':
case 'x':
case 'X':
case 's':
case 't':
case 'u':
case 'g':
case 'o':
case 'a':
case ',':
case '+':
case '=':
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
/* Support nonportable uses like "chmod -w", but diagnose
surprises due to umask confusion. Even though "--", "--r",
etc., are valid modes, there is no "case '-'" here since
getopt_long reserves leading "--" for long options. */
ยกตัวอย่างของคุณ:
chmod a-r file.txtจะเป็นการเรียกที่แข็งแกร่งที่สุดchmod +r file.txt ใช้งานได้เนื่องจากอาร์กิวเมนต์แรกถูกตีความตำแหน่งเป็นโหมดchmod -r file.txtยังใช้งานได้เพราะ-rถูกตีความว่าเป็นrตัวเลือกสั้น ๆและใส่กล่องพิเศษchmod -- -r file.txtถูกต้องและทำงานได้เนื่องจาก-rถูกตีความตำแหน่งเป็นโหมด ความแตกต่างนี้จากกรณีที่โดยไม่ต้อง--เพราะไม่ได้ตีความว่าเป็นตัวเลือก---rchmod file.txt -rยังใช้งานได้เพราะ-rถูกตีความว่าเป็นrตัวเลือกสั้น ๆและใส่กล่องพิเศษ ตัวเลือกไม่ขึ้นอยู่กับตำแหน่ง เทคนิคนี้เป็นการดูหมิ่นที่ไม่มีเอกสารทางเทคนิคchmod file.txt +rไม่ทำงานเนื่องจาก+rตัวถูกดำเนินการไม่ใช่ตัวเลือก ตัวถูกดำเนินการแรก ( file.txt) ถูกตีความว่าเป็นโหมด ... และล้มเหลวในการแยกวิเคราะห์getopt คำสั่งไม่ห้องสมุดประจำในส่วนที่ 3 ประการที่สองนั่นคือการอ้างอิงถึงoptstringคือรายการของตัวเลือกที่ยอมรับ (ในchmodแหล่งที่มาoptstringถูกตั้งค่าเป็น"Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::") ส่วน "โหมดการสแกน" ที่เชื่อมโยงนั้นไม่มีส่วนเกี่ยวข้องกับอาเรย์อาร์กิวเมนต์ argvที่มี args ที่ส่งผ่านเข้าไปในโปรแกรม
a+rwxและทำอะไรเช่นchmod * +rนั้นและa+rwxไฟล์จะเกิดขึ้นก่อนในการขยายแบบกลม