การเปลี่ยนชื่อส่งคืน“ ไม่อนุญาตให้ bareword” เมื่อพยายามพิมพ์อักษรย่อส่วนของชื่อไฟล์หลาย ๆ ไฟล์


12

ฉันมีสองไฟล์ในโฟลเดอร์บน Ubuntu 16.04 ของฉัน:

a1.dat
b1.DAT

ฉันต้องการเปลี่ยนชื่อb1.DATเป็นb1.datดังนั้นฉันจะมีไฟล์ต่อไปนี้ซึ่งเป็นผลลัพธ์ในโฟลเดอร์:

a1.dat
b1.dat

ฉันพยายาม (ไม่สำเร็จ):

$ rename *.DAT *.dat
Bareword "b1" not allowed while "strict subs" in use at (user-supplied code).
Bareword "DAT" not allowed while "strict subs" in use at (user-supplied code).

และ

$ find . -iname "*.DAT" -exec rename DAT dat '{}' \;
Bareword "DAT" not allowed while "strict subs" in use at (user-supplied code).
Bareword "DAT" not allowed while "strict subs" in use at (user-supplied code).

การค้นหาสิ่งนี้ไม่ได้แก้ปัญหาที่มีความหมาย ...


คุณอาจต้องการเรียนรู้เกี่ยวกับ mmv
PlasmaHH

คำตอบ:


14

ข้อผิดพลาดที่ดูเหมือนว่ามันมาจาก renamePerl คุณต้องใช้ข้อความ แต่คุณต้องระบุเฉพาะส่วนที่คุณต้องการเปลี่ยนสไตล์การค้นหาและแทนที่ ไวยากรณ์เป็นดังนี้:

rename -n 's/\.DAT/\.dat/' *

ลบ-nหลังจากการทดสอบเพื่อเปลี่ยนชื่อไฟล์จริง

หากต้องการรวมไฟล์ที่ซ่อนอยู่ให้เปลี่ยนการตั้งค่า glob ก่อนเรียกใช้คำสั่ง:

shopt -s dotglob

หากคุณต้องการเปลี่ยนชื่อไฟล์ซ้ำคุณสามารถใช้

shopt -s globstar
rename -n 's/\.DAT/\.dat/' **

หรือหากมีหลายเส้นทางในหรือต่ำกว่าไดเรกทอรีปัจจุบันที่ไม่ได้จบด้วย.DATคุณควรระบุเส้นทางเหล่านั้นในคำสั่งที่สอง:

rename -n 's/\.DAT/\.dat/' **/*.DAT

สิ่งนี้จะเร็วขึ้นหากไฟล์ของคุณมีชื่อต่าง ๆ ที่ไม่ได้ลงท้าย.DATด้วย [1]

หากต้องการปิดการตั้งค่าเหล่านี้คุณสามารถใช้shopt -uเช่นshopt -u globstarแต่จะปิดไว้ตามค่าเริ่มต้นและจะปิดเมื่อคุณเปิดเชลล์ใหม่

หากผลลัพธ์ในรายการอาร์กิวเมนต์ยาวเกินไปคุณสามารถใช้ตัวอย่างเช่นfind:

find -type f -name "*.DAT" -exec rename -n -- 's/\.DAT/\.dat/' {} \;

หรือดีกว่า

find -type f -name "*.DAT" -exec rename -n -- 's/\.DAT/\.dat/' {} +

ใช้find ... -execกับ+เร็วกว่าการใช้\;เพราะมันสร้างรายการอาร์กิวเมนต์จากไฟล์ที่พบ เดิมทีฉันคิดว่ามันเป็นไปไม่ได้ที่คุณจะใช้มันเพราะคุณบอกว่าคุณกำลังมีargument list too longปัญหา แต่ตอนนี้ฉันรู้แล้วว่ารายการจะแตกอย่างชาญฉลาดในการเรียกใช้คำสั่งหลายครั้งตามที่จำเป็นเพื่อหลีกเลี่ยงปัญหานั้น[2]

เนื่องจากrenameจะประมวลผลทุกชื่อไฟล์ในวิธีเดียวกันจึงไม่สำคัญว่ารายการอาร์กิวเมนต์จะยาวเท่าใดเนื่องจากสามารถแยกได้อย่างปลอดภัยผ่านการเรียกใช้หลายรายการ หากคำสั่งที่คุณใช้กับ-execไม่ยอมรับอาร์กิวเมนต์หลายตัวหรือต้องการให้อาร์กิวเมนต์อยู่ในลำดับที่เฉพาะเจาะจงหรือด้วยเหตุผลอื่นใดที่แยกรายการอาร์กิวเมนต์จะทำให้สิ่งที่ไม่ต้องการเกิดขึ้นคุณสามารถใช้\;ซึ่งทำให้คำสั่งถูกเรียกใช้ครั้งเดียว สำหรับทุกไฟล์ที่พบ (หากรายการอาร์กิวเมนต์ยาวเกินไปสำหรับวิธีอื่นมันจะใช้เวลานาน!)


ขอบคุณEliah Kaganมากสำหรับคำแนะนำที่มีประโยชน์มากในการปรับปรุงคำตอบนี้:

[1] การระบุชื่อไฟล์เมื่อทำการวนรอบ
[2] find ... -execมี+แยกรายการอาร์กิวเมนต์


ขอบคุณ จะทำซ้ำ (สำหรับไฟล์ทั้งหมดในโฟลเดอร์ย่อยทั้งหมด) ได้อย่างไร?
Samo

@Samo ดูการแก้ไขของฉัน :)
Zanna

ไม่ทำงาน: $ rename 's / \. DAT / \. dat /' ** bash: / usr / bin / เปลี่ยนชื่อ: รายการอาร์กิวเมนต์ยาวเกินไป
Samo

1
@Samo คุณต้องลบการ-nเปลี่ยนชื่อหลังจากการทดสอบ - เป็นเพียงการแสดงสิ่งที่จะเปลี่ยน
Zanna

1
บน Centos และ Arch การเปลี่ยนชื่อจะไม่แสดงพฤติกรรมนี้ ฉันมาที่นี่จากการใช้ Debian บน WSL ไวยากรณ์นี้ใช้งานได้
xtian

6

คุณทำได้:

rename -n 's/DAT$/\L$&/' *.DAT

วาง-nเพื่อให้การเปลี่ยนชื่อเกิดขึ้นจริง

  • รูปแบบ glob *.DATตรงกับไฟล์ทั้งหมดสิ้นสุดลงใน.DATไดเรกทอรีปัจจุบัน

  • ในการrenameเปลี่ยนตัว 's, DAT$จับคู่DATที่จุดสิ้นสุด

  • \L$&ทำให้การแข่งขันลดลงทั้งหมด $&หมายถึงการแข่งขันทั้งหมด

หากคุณต้องการทำเพื่อb1.DAT:

rename -n 's/DAT$/\L$&/' b1.DAT

ตัวอย่าง:

% rename -n 's/DAT$/\L$&/' *.DAT
rename(b1.DAT, b1.dat)

4

คำตอบอื่น ๆได้กล่าวถึงประเด็นสำคัญข้อใดข้อหนึ่งในสองข้อนี้: วิธีการดำเนินการเปลี่ยนชื่อที่คุณต้องการให้สำเร็จ วัตถุประสงค์ของคำตอบนี้คือเพื่ออธิบายว่าทำไมคำสั่งของคุณไม่ทำงานรวมถึงความหมายของข้อความแสดงข้อผิดพลาด "bareword ไม่อนุญาต" แปลก ๆ ในบริบทของrenameคำสั่ง

ส่วนแรกของคำตอบนี้เกี่ยวกับความสัมพันธ์ระหว่างrenameและ Perl และวิธีการrenameใช้อาร์กิวเมนต์บรรทัดคำสั่งแรกที่คุณส่งผ่านซึ่งเป็นอาร์กิวเมนต์รหัส ส่วนที่สองเป็นเรื่องเกี่ยวกับวิธีที่เชลล์ทำการขยาย - โดยเฉพาะอย่างยิ่งทำให้เป็นวงกลม - เพื่อสร้างรายการอาร์กิวเมนต์ ส่วนที่สามเกี่ยวกับสิ่งที่เกิดขึ้นในรหัส Perl ที่ให้ข้อผิดพลาด "Bareword ไม่อนุญาต" สุดท้ายส่วนที่สี่เป็นการสรุปขั้นตอนทั้งหมดที่เกิดขึ้นระหว่างการป้อนคำสั่งและรับข้อผิดพลาด

1. เมื่อrenameให้ข้อความผิดพลาดแปลกเพิ่ม "Perl" ในการค้นหาของคุณ

ใน Debian และ Ubuntu renameคำสั่งคือสคริปต์Perlที่ทำการเปลี่ยนชื่อไฟล์ สำหรับรีลีสที่เก่ากว่า - รวมถึง 14.04 LTS ซึ่งยังคงได้รับการสนับสนุนในขณะที่เขียนนี้ - มันเป็นลิงค์สัญลักษณ์ (ชี้ทางอ้อม ) ไปยังprenameคำสั่ง ในรีลีสที่ใหม่กว่าจะชี้ไปที่file-renameคำสั่งที่ใหม่กว่า คำสั่งเปลี่ยนชื่อ Perl ทั้งสองนั้นทำงานเหมือนกันส่วนใหญ่และฉันจะอ้างถึงพวกเขาทั้งคู่ว่าเป็นrenameคำตอบที่เหลือ

เมื่อคุณใช้renameคำสั่งคุณไม่เพียงแค่เรียกใช้โค้ด Perl ที่คนอื่นเขียน คุณกำลังเขียนโค้ด Perl ของคุณเองและบอกrenameให้เรียกใช้ เพราะนี่คือครั้งแรกที่อาร์กิวเมนต์บรรทัดคำสั่งที่คุณส่งผ่านไปยังrenameคำสั่งอื่น ๆ นอกเหนือจากข้อโต้แย้งตัวเลือกเช่น-n,ประกอบด้วยรหัส Perl ที่เกิดขึ้นจริง renameคำสั่งใช้รหัสนี้ในการดำเนินงานในแต่ละpathnamesที่คุณผ่านมันเป็นอาร์กิวเมนต์บรรทัดคำสั่งที่ตามมา (หากคุณไม่ผ่านอาร์กิวเมนต์ชื่อพา ธ ใด ๆ ให้renameอ่านชื่อพา ธ จากอินพุตมาตรฐานแทนหนึ่งรายการต่อบรรทัด)

รหัสถูกเรียกใช้ภายในลูปซึ่งวนซ้ำหนึ่งครั้งต่อชื่อพา ธ ที่ด้านบนของการวนซ้ำแต่ละครั้งก่อนที่โค้ดของคุณจะรัน$_ตัวแปรพิเศษจะถูกกำหนดชื่อพา ธ ที่กำลังประมวลผลอยู่ หากรหัสของคุณทำให้ค่า$_ที่จะเปลี่ยนเป็นอย่างอื่นไฟล์นั้นจะถูกเปลี่ยนชื่อให้มีชื่อใหม่

หลายคนแสดงออกใน Perl ทำงานโดยปริยายใน$_ตัวแปรเมื่อพวกเขาจะไม่ได้รับการแสดงออกอื่น ๆ ที่จะใช้เป็นตัวถูกดำเนินการ ยกตัวอย่างเช่นการแสดงออกทดแทน$str =~ s/foo/bar/การเปลี่ยนแปลงเกิดขึ้นครั้งแรกของfooในสตริงที่จัดขึ้นโดย$str ตัวแปรที่จะหรือใบมันไม่เปลี่ยนแปลงถ้ามันไม่ได้มีbar fooหากคุณเพียงแค่เขียนs/foo/bar/โดยไม่ต้องชัดเจนโดยใช้ผู้ประกอบการแล้วมันทำงานบน นี้คือจะบอกว่าเป็นชื่อสั้น=~$_s/foo/bar/$_ =~ s/foo/bar/

เป็นเรื่องปกติที่จะผ่านแสดงออกจะเป็นอาร์กิวเมนต์รหัส (เช่นอาร์กิวเมนต์บรรทัดคำสั่งครั้งแรก) แต่คุณไม่จำเป็นต้อง คุณสามารถให้รหัส Perl ใด ๆ ที่คุณต้องการให้มันทำงานภายในลูปเพื่อตรวจสอบแต่ละค่าของและ (ตามเงื่อนไข) แก้ไขมันs///rename$_

สิ่งนี้มีผลลัพธ์ที่ยอดเยี่ยมและเป็นประโยชน์มากมาย แต่ส่วนใหญ่ของพวกเขานั้นดีเกินกว่าขอบเขตของคำถามและคำตอบนี้ เหตุผลหลักที่ฉันนำมาไว้ที่นี่ - ในความเป็นจริงเหตุผลหลักที่ฉันตัดสินใจโพสต์คำตอบนี้ - คือการทำให้จุดที่เพราะอาร์กิวเมนต์แรกที่renameเป็นจริงรหัส Perl ทุกครั้งที่คุณได้รับข้อความผิดพลาดแปลกและคุณ มีปัญหาในการค้นหาข้อมูลเกี่ยวกับมันโดยการค้นหาคุณสามารถเพิ่ม "Perl" ลงในสตริงการค้นหา (หรือแม้แต่แทนที่ "เปลี่ยนชื่อ" ด้วย "Perl" บางครั้ง) และคุณมักจะพบคำตอบ

2. rename *.DAT *.datการrenameสั่งไม่เคยเห็น*.DAT!

โดยทั่วไปคำสั่งเช่นrename s/foo/bar/ *.txtนั้นจะไม่ส่งผ่าน*.txtเป็นอาร์กิวเมนต์บรรทัดคำสั่งไปยังrenameโปรแกรมและคุณไม่ต้องการให้เว้นเสียแต่ว่าคุณจะมีไฟล์ที่มีชื่อเป็นตัวอักษร*.txtซึ่งหวังว่าคุณจะไม่

renameไม่ได้ตีความรูปแบบ globชอบ*.txt, *.DAT, *.dat, x*, *yหรือ*เมื่อผ่านไปเป็นข้อโต้แย้งชื่อพา ธ แต่เชลล์ของคุณจะทำการขยายชื่อพา ธบนมัน (ซึ่งเรียกว่าการขยายชื่อไฟล์และเรียกอีกอย่างว่าการทำให้กลม) สิ่งนี้เกิดขึ้นก่อนที่renameยูทิลิตี้จะทำงาน เปลือกขยาย globs เข้า pathnames renameที่อาจเกิดขึ้นหลายครั้งและผ่านพวกเขาทั้งหมดเป็นอาร์กิวเมนต์บรรทัดคำสั่งที่แยกจากกันไป ใน Ubuntu เชลล์แบบโต้ตอบของคุณคือBashยกเว้นว่าคุณได้ทำการเปลี่ยนแปลงซึ่งเป็นสาเหตุที่ฉันเชื่อมโยงไปยังคู่มืออ้างอิง Bashด้านบน

มีสถานการณ์หนึ่งที่รูปแบบ glob อาจถูกส่งผ่านเป็นอาร์กิวเมนต์บรรทัดคำสั่งเดียวที่ยังไม่ขยายไปที่rename: เมื่อมันไม่ตรงกับไฟล์ใด ๆ กระสุนที่แตกต่างกันแสดงพฤติกรรมเริ่มต้นที่แตกต่างกันในสถานการณ์นี้ แต่พฤติกรรมเริ่มต้นของ Bash คือการส่งผ่าน glob อย่างแท้จริง อย่างไรก็ตามคุณไม่ค่อยต้องการสิ่งนี้! หากคุณไม่ต้องการมันแล้วคุณควรตรวจสอบให้แน่ใจว่ารูปแบบจะไม่ขยายตัวโดยอ้างว่ามัน นี้ไปสำหรับการส่งผ่านข้อโต้แย้งคำสั่งใด ๆ renameที่ไม่เพียงเพื่อ

อ้างไม่ได้เป็นเพียง globbing (ส่วนขยายชื่อไฟล์) เนื่องจากมีการขยายตัวอื่น ๆที่มีประสิทธิภาพเปลือกของคุณในข้อความ unquoted และสำหรับบางส่วนของพวกเขา แต่คนอื่นไม่ได้นอกจากนี้ยังมีข้อความที่อยู่ใน" "คำพูด โดยทั่วไปทุกเวลาที่คุณต้องการที่จะผ่านการโต้แย้งที่มีตัวละครที่อาจจะได้รับการปฏิบัติเป็นพิเศษโดยเปลือกรวมถึงช่องว่างคุณควรพูดมันยิ่งกับคำพูด' '

รหัส Perl s/foo/bar/ไม่ได้มีอะไรที่ได้รับการปฏิบัติเป็นพิเศษโดยเปลือก แต่ก็จะได้รับความคิดที่ดีสำหรับผมที่จะได้ยกมาที่มากเกินไป - 's/foo/bar/'และการเขียน (ในความเป็นจริงเหตุผลเดียวที่ฉันไม่ได้ก็คือว่ามันจะทำให้เกิดความสับสนให้กับผู้อ่านบางคนที่ผมยังไม่ได้พูดคุยเกี่ยวกับ quoting.) เหตุผลที่ผมพูดนี้จะได้รับที่ดีเป็นเพราะมันเป็นเรื่องธรรมดามากว่ารหัส Perl ไม่ประกอบด้วย ตัวอักษรดังกล่าวและถ้าฉันต้องเปลี่ยนรหัสนั้นฉันอาจจำไม่ได้ว่าตรวจสอบว่าจำเป็นต้องมีการอ้างอิงหรือไม่ ในทางตรงกันข้ามถ้าคุณต้องการให้เปลือกขยายตัวกลมมันจะต้องไม่ถูกยกมา

3. ล่ามภาษา Perl แปลว่า "ห้ามใช้คำ bareword"

ข้อผิดพลาดที่คุณแสดงให้เห็นในคำถามของคุณแสดงให้เห็นว่าเมื่อคุณวิ่งrename *.DAT *.dat, เปลือกของคุณขยายตัว*.DATในรายการหนึ่งหรือมากกว่าหนึ่งชื่อไฟล์และที่แรกb1.DATของชื่อไฟล์เหล่านั้น อาร์กิวเมนต์ที่ตามมาทั้งหมด - ทั้งคู่ถูกขยายจาก*.DATและขยายจาก - มา*.datหลังจากอาร์กิวเมนต์นั้นดังนั้นพวกเขาจะถูกตีความว่าเป็นชื่อพา ธ

เพราะสิ่งที่วิ่งจริง ๆ แล้วเป็นเช่นrename b1.DAT ...นั้นและเนื่องจากrenameถือเป็นอาร์กิวเมนต์ที่ไม่ใช่ตัวเลือกตัวแรกเป็นรหัส Perl คำถามจะกลายเป็น: ทำไมb1.DATข้อผิดพลาด "bareword ไม่อนุญาต" เหล่านี้เมื่อคุณเรียกใช้เป็นรหัส Perl

Bareword "b1" not allowed while "strict subs" in use at (user-supplied code).
Bareword "DAT" not allowed while "strict subs" in use at (user-supplied code).

ในเชลล์เราเสนอราคาสตริงของเราเพื่อปกป้องพวกเขาจากการขยายเชลล์โดยไม่ตั้งใจซึ่งจะเปลี่ยนพวกมันเป็นสตริงอื่นโดยอัตโนมัติ (ดูหัวข้อด้านบน) เชลล์เป็นภาษาโปรแกรมวัตถุประสงค์พิเศษที่ทำงานแตกต่างจากภาษาที่ใช้งานทั่วไปมาก (และไวยากรณ์และความหมายแปลก ๆของมันสะท้อนให้เห็น) แต่ Perl เป็นภาษาโปรแกรมทั่วไปและเช่นเดียวกับภาษาโปรแกรมทั่วไปส่วนใหญ่จุดประสงค์หลักของการเขียนข้อความใน Perl ไม่ใช่เพื่อปกป้องสตริง แต่พูดถึงมันทั้งหมด นี่เป็นวิธีที่ภาษาการเขียนโปรแกรมส่วนใหญ่คล้ายกับภาษาธรรมชาติ. ในภาษาอังกฤษและสมมติว่าคุณมีสุนัข "สุนัขของคุณ" เป็นวลีสองคำในขณะที่สุนัขของคุณเป็นสุนัข ในทำนองเดียวกันในเพิร์ล'$foo'เป็นสตริงในขณะที่บางสิ่งบางอย่างที่มีชื่อเป็น$foo$foo

แต่แตกต่างเพียงเกี่ยวกับทุกอื่น ๆ วัตถุประสงค์ทั่วไปการเขียนโปรแกรมภาษา Perl จะยังบางครั้งการตีความข้อความ unquoted เป็นกล่าวขวัญสตริง - สตริงที่เป็น "เดียวกัน" ขณะที่มันในแง่ที่ว่ามันถูกสร้างขึ้นจากตัวละครเดียวกันใน คำสั่งเดียวกัน มันจะพยายามตีความรหัสด้วยวิธีนั้นถ้าเป็น bareword (ไม่มี$หรือ sigil อื่น ๆ , ดูด้านล่าง) และหลังจากที่มันไม่สามารถหาความหมายอื่นใดที่จะให้มัน จากนั้นก็จะใช้มันเป็นสตริงจนกว่าคุณจะบอกว่ามันไม่ได้ไปด้วยการทำให้ข้อ จำกัด

โดยทั่วไปแล้วตัวแปรใน Perl จะเริ่มต้นด้วยอักขระคั่นที่เรียกว่าsigilซึ่งระบุประเภทของตัวแปร ยกตัวอย่างเช่น$หมายความว่าสเกลาร์ , @วิธีอาร์เรย์และ%วิธีกัญชา ( มีคนอื่น ๆ ) ไม่ต้องกังวลหากคุณพบว่าสับสน (หรือน่าเบื่อ) เพราะฉันแค่นำมันมาพูดว่าเมื่อชื่อที่ถูกต้องปรากฏในโปรแกรม Perl แต่ไม่ได้นำหน้าด้วยชื่อนั้น มีการกล่าวถึงเป็น bareword

Barewords ให้บริการตามวัตถุประสงค์ต่าง ๆ แต่โดยปกติแล้วพวกเขาหมายถึงฟังก์ชั่นในตัวหรือรูทีนย่อยที่ผู้ใช้กำหนดซึ่งได้รับการกำหนดในโปรแกรม (หรือในโมดูลที่ใช้โดยโปรแกรม) Perl ไม่มีฟังก์ชั่นในตัวที่เรียกว่าb1หรือDATดังนั้นเมื่อล่าม Perl เห็นรหัสb1.DATก็พยายามที่จะรักษาb1และDATเป็นชื่อของรูทีนย่อย สมมติว่าไม่มีการกำหนดรูทีนย่อยดังกล่าวสิ่งนี้จะล้มเหลว จากนั้นข้อ จำกัด ที่ให้ไว้ยังไม่ได้เปิดใช้งานจะถือว่าเป็นข้อ จำกัด สิ่งนี้จะใช้ได้แม้ว่าคุณตั้งใจจะทำสิ่งนี้จริงหรือไม่ก็เป็นสิ่งที่เดาได้ .ผู้ประกอบการของ Perl เชื่อมสตริงเข้าด้วยกันดังนั้นb1.DATประเมินค่าสตริงb1DAT. นั่นคือb1.DATเป็นวิธีที่ดีที่จะเขียนสิ่งที่ต้องการหรือ'b1' . 'DAT'"b1" . "DAT"

คุณสามารถทดสอบนี้ออกเองโดยใช้คำสั่งperl -E 'say b1.DAT'ที่ผ่าน Perl สคริปต์สั้นsay b1.DATเพื่อล่าม Perl b1DATซึ่งไหลมันพิมพ์ (ในคำสั่งนั้น' 'คำพูดที่บอกเปลือกจะผ่านsay b1.DATเป็นอาร์กิวเมนต์บรรทัดคำสั่งเดียวมิฉะนั้นพื้นที่ที่จะก่อให้เกิดsayและb1.DATจะได้รับการแยกวิเคราะห์เป็นคำที่แยกจากกันและperlจะได้รับพวกเขาเป็นข้อโต้แย้งที่แยกต่างหาก. perlไม่ได้เห็นคำพูดของตัวเองเป็นเชลล์ลบออก )

แต่ตอนนี้ลองเขียนuse strict;ในสคริปต์ Perl sayก่อน ตอนนี้มันล้มเหลวด้วยข้อผิดพลาดชนิดเดียวกันที่คุณได้รับจากrename:

$ perl -E 'use strict; say b1.DAT'
Bareword "b1" not allowed while "strict subs" in use at -e line 1.
Bareword "DAT" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.

สิ่งนี้เกิดขึ้นเพราะuse strict;ห้ามล่าม Perl ไม่ให้ถือ barewords เป็นสตริง หากต้องการห้ามฟีเจอร์นี้มันจะเพียงพอที่จะเปิดใช้งานsubsข้อ จำกัด คำสั่งนี้สร้างข้อผิดพลาดเช่นเดียวกับข้างบน:

perl -E 'use strict "subs"; say b1.DAT'

แต่โดยปกติโปรแกรมเมอร์ Perl จะเพิ่งเขียนuse strict;ซึ่งทำให้subsข้อ จำกัด และอีกสองคน use strict;เป็นการปฏิบัติที่แนะนำโดยทั่วไป ดังนั้นrenameคำสั่งทำสิ่งนี้เพื่อรหัสของคุณ นั่นคือเหตุผลที่คุณได้รับข้อความแสดงข้อผิดพลาด

4. โดยสรุปนี่คือสิ่งที่เกิดขึ้น:

  1. เชลล์ของคุณส่งผ่านb1.DATเป็นอาร์กิวเมนต์บรรทัดคำสั่งแรกซึ่งrenameถือว่าเป็นรหัส Perl เพื่อทำงานเป็นวนรอบสำหรับแต่ละอาร์กิวเมนต์ชื่อพา ธ
  2. สิ่งนี้ถูกนำไปหมายถึงb1และDATเชื่อมต่อกับ.ผู้ประกอบการ
  3. b1และDATไม่ได้ขึ้นต้นด้วย sigils ดังนั้นจึงถือว่าเป็น barewords
  4. barewords ทั้งสองนั้นจะถูกใช้เป็นชื่อของฟังก์ชันในตัวหรือรูทีนย่อยที่ผู้ใช้กำหนด แต่ไม่มีสิ่งใดที่มีชื่อเหล่านั้น
  5. หากไม่ได้เปิดใช้งาน "เข้มงวดส่วนย่อย" พวกเขาจะได้รับการปฏิบัติเช่นเดียวกับการแสดงออกของสตริง'b1'และ'DAT'และเชื่อมต่อกัน ซึ่งอยู่ไกลจากสิ่งที่คุณตั้งใจจะให้แสงสว่างซึ่งคุณสมบัตินี้มักจะไม่เป็นประโยชน์
  6. แต่ "ผู้ใต้บังคับบัญชาอย่างเคร่งครัด" ถูกเปิดใช้งานเพราะrenameช่วยให้ทุกข้อ จำกัด ( vars, refsและsubs) ดังนั้นคุณได้รับข้อผิดพลาดแทน
  7. renameออกจากเนื่องจากข้อผิดพลาดนี้ -nเพราะการจัดเรียงของข้อผิดพลาดนี้เกิดขึ้นในช่วงต้นไม่มีการเปลี่ยนชื่อไฟล์พยายามทำให้ถึงแม้ว่าคุณไม่ได้ผ่าน นี่เป็นสิ่งที่ดีซึ่งมักจะปกป้องผู้ใช้จากการเปลี่ยนชื่อไฟล์โดยไม่ตั้งใจและบางครั้งอาจสูญหายจากข้อมูลจริง

ขอบคุณไปที่Zannaที่ช่วยฉันจัดการข้อบกพร่องที่สำคัญหลายอย่างในแบบร่างที่ดีกว่าของคำตอบนี้ หากไม่มีเธอคำตอบนี้น่าจะสมเหตุสมผลน้อยลงและอาจไม่สามารถโพสต์ได้เลย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.