rename
ช่วยให้คุณกำหนดโดยตรงกับ$_
ซึ่งเหมาะสำหรับปัญหานี้
แม้ว่าข้อโต้แย้งของรหัสที่เราส่งไปยังrename
โปรแกรมอรรถประโยชน์ของPerl มักจะทำการจับคู่และทดแทน (ด้วยs/
) และเป็นที่ยอมรับโดยสิ้นเชิงในการแก้ปัญหานี้ในแบบที่ไม่จำเป็นสำหรับกรณีเช่นนี้ซึ่งคุณไม่ได้ตรวจสอบหรือ การนำข้อความชื่อไฟล์เก่ามาใช้ซ้ำ rename
ช่วยให้คุณเขียนเพียงเกี่ยวกับการใด ๆรหัส Perl s/
/e
และมันไม่จำเป็นต้องได้รับการฝังอยู่ภายใน ฉันขอแนะนำให้ใช้คำสั่งเช่นนี้:
rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' *
หรือหากคุณรู้สึกอยากโกนหนวดสักสองสามตัว:
rename -n '$_ = sprintf "AS%02d.txt", ++our$i' *
(มันสามารถทำให้สั้นลงได้ แต่ไม่ลดทอนความชัดเจน)
ทั้งสองคำสั่งเหล่านั้นทำสิ่งเดียวกัน แต่ละรายการแสดงการดำเนินการเปลี่ยนชื่อที่จะดำเนินการ เมื่อคุณลองใช้แล้วคุณจะพอใจกับผลลัพธ์ให้เรียกใช้อีกครั้งโดยไม่มี-n
ตัวเลือก ขณะที่เขียนนี้จะผลิตชื่อไฟล์AS01.txt
, AS02.txt
, ... , AS10.txt
, AS11.txt
และอื่น ๆ คุณสามารถแก้ไขได้ตามต้องการจากนั้นลบ-n
เมื่อคุณต้องการสิ่งที่คุณเห็น
หากคุณต้องการแผ่นที่มีความกว้างมากกว่า 2 ให้แทนที่2
ด้วยจำนวนที่มากขึ้น ตัวอย่างเช่นถ้าด้วยเหตุผลบางอย่างที่คุณต้องการชื่อไฟล์ที่ต้องการAS00000000000001.txt
คุณจะเข้ามาแทนที่ด้วย%02d
%014d
หากคุณไม่ต้องการ padding ที่ทั้งหมด - แม้ว่าที่จะทำให้ไฟล์ของคุณปรากฏในคำสั่งที่ไม่ใช่ตัวเลขเมื่อคุณรายการพวกเขาในภายหลัง! - แล้วคุณสามารถแทนที่มีเพียง%02d
%d
มันทำงานอย่างไร เชลล์ของคุณขยาย *
เข้าไปในรายการไฟล์ก่อนที่มันจะรันrename
คำสั่ง รายการจะถูกจัดเรียงตามพจนานุกรม (เช่นตัวอักษร) ตามการตั้งค่าตำแหน่งที่ตั้งปัจจุบันของคุณ rename
รับชื่อไฟล์เป็นอาร์กิวเมนต์บรรทัดคำสั่งและประมวลผลตามลำดับที่ปรากฏ นิพจน์++$i
ประเมินค่ามากกว่าหนึ่งค่าปัจจุบันของตัวแปร$i
และตั้งค่าตัวแปรเป็นค่า$i
ที่เพิ่มขึ้นใหม่ ค่านี้ถูกส่งผ่านไปยังsprintf
ซึ่งจัดรูปแบบและวางไว้ในข้อความอื่น ข้อความนี้ถูกกำหนดให้กับตัวแปรพิเศษโดยตรง$_
ซึ่งเก็บชื่อไฟล์ เนื่องจากrename
ไฟล์กระบวนการตามลำดับที่ส่งเป็นอาร์กิวเมนต์จะถูกนับตามลำดับ
คุณอาจสังเกตเห็นความคล้ายคลึงกับคำตอบของ Oli !
ทั้งประกาศและเพิ่มตัวแปรตัวนับและทั้งคู่ก็ใช้sprintf
วิธีเดียวกันในการฝังค่าของตัวนับนั้นไปทางด้านซ้ายด้วยค่าศูนย์ในข้อความอื่น ๆ ของชื่อไฟล์ใหม่ (ข้อมูลในคำตอบอย่างใดอย่างหนึ่งเกี่ยวกับวิธีการแผ่นด้วยศูนย์ - และเปลี่ยนความกว้างช่องว่างภายใน -. แม้ใช้อย่างเท่าเทียมกันทั้งสอง) เหตุผลที่พวกเขามีความคล้ายคลึงกันเพื่อให้เป็นว่าวิธีการในการที่คำตอบเก่าเป็นจริงทำเพียงแค่นี้1แต่ ด้วยขั้นตอนพิเศษที่มีประโยชน์สำหรับปัญหามากมาย แต่ไม่จำเป็นจริงๆสำหรับขั้นตอนนี้
สำหรับการเปรียบเทียบนี่คือสิ่งที่คำสั่งที่สองในคำตอบนั้นดูเหมือนว่าได้รับการแก้ไขให้ใช้สไตล์ที่ฉันใช้ที่นี่ (และเพื่อเพิ่มความกว้างเป็น 2 ตามที่ฉันได้ทำที่นี่แทนที่จะเป็น 3):
rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' *
ส่วนระหว่างs/.+/
และ/e
ในคำสั่งนั้นตอนนี้เหมือนกับนิพจน์ที่ฉันกำหนดให้$_
(เช่นรหัสทางด้านขวาของ=
โอเปอเรเตอร์) ในคำสั่งแรกในคำตอบนี้
- ตัว
s/
ดำเนินการพยายามจับคู่ข้อความ (ชื่อไฟล์ที่เชลล์ของคุณขยายจาก*
และผ่านเป็นอาร์กิวเมนต์บรรทัดคำสั่งเมื่อรันrename
) ด้วยนิพจน์ทั่วไปและทำการทดแทน /
กำลังใช้เป็นตัวคั่นเพื่อแยกส่วนต่าง ๆ ของs
นิพจน์ ส่วนแรก.+
,, คือการแสดงออกปกติ; มันตรงกับใด ๆ1ตัวอักษร ( .
)และไม่ให้หนึ่งครั้งหรือมากกว่า (+
) เนื่องจากชื่อไฟล์จะไม่ว่างเปล่า - มีความยาวอย่างน้อยหนึ่งตัวอักษร - นี่เป็นวิธีหนึ่งในการจับคู่ชื่อไฟล์1ไฟล์
- จากนั้นก็จะผลิตข้อความจากการแข่งขันแต่ละครั้ง - นั่นคือจากแต่ละชื่อไฟล์ทั้งหมด -
our $i; sprintf "AS%02d.txt", ++$i
ประกอบด้วย สิ่งนี้จะสร้างชื่อไฟล์ใหม่ โดยทั่วไปแล้วหนึ่งใช้s/
ในการผลิตข้อความที่(a)แทนที่ข้อความที่ตรงกับเพียงส่วนหนึ่งของชื่อไฟล์หรือ(b)ขึ้นอยู่กับข้อความที่ตรงกันในบางวิธี (ตัวอย่างเช่นมันอาจใช้ตัวแปรพิเศษเช่น$&
ขยาย การแข่งขัน) ในกรณีนี้ข้อความที่ตรงกันไม่ได้ถูกใช้งานเลย
- โดยปกติแล้วข้อความที่
our $i; sprintf "AS%02d.txt", ++$i
ถูกแทนที่จะถูกใช้เป็นชื่อไฟล์ไม่ใช่เรียกใช้เป็นรหัส แต่การ/e
ตั้งค่าสถานะในตอนท้ายทำให้ข้อความนั้นถือว่าเป็นซอร์สโค้ด Perl และประเมินและใช้ค่าที่สร้างขึ้นโดยการทำเช่นนั้น (ในกรณีนี้คือค่าส่งคืนของsprintf
ฟังก์ชันในตัวของ Perl ) เป็นชื่อไฟล์ใหม่
แม้ว่าฉันคิดว่าวิธีการที่ฉันแสดงไว้ที่นี่เป็นวิธีการที่ชัดเจนและง่ายกว่าสำหรับปัญหานี้มากกว่าวิธีการอื่นที่ใช้s/
ด้วย/e
แต่ก็เป็นเรื่องดีที่จะต้องตระหนักถึงเทคนิคนั้นเพราะมันเหมาะสมกับปัญหาการเปลี่ยนชื่อไฟล์อื่น ๆ หรือบางส่วนของชื่อไฟล์ต้นฉบับจะถูกตรวจสอบและ / หรือเก็บไว้ ฉันแนะนำโพสต์บล็อกนี้โดยOli (ผู้เขียนคำตอบนั้นด้วย ) ซึ่งรวมถึงตัวอย่างดังกล่าว
1 เทคนิคมีคือความแตกต่างในการทำงานของ$_ =
คำสั่งและs/
/e
คำสั่ง ในการแสดงออกปกติ.+
ก็ไม่เป็นความจริงอย่างเคร่งครัดที่.
ตรงกับใด ๆของตัวละครเพราะมันไม่ตรงกับขึ้นบรรทัดใหม่ คุณอาจไม่ควรใช้ชื่อไฟล์กับการขึ้นบรรทัดใหม่ แต่คุณสามารถและบางครั้งไฟล์จะถูกตั้งชื่อโดยวิธีนี้โดยไม่ตั้งใจ ถ้าคุณรู้สึกว่ามันแตกต่างการส่งออกของกับที่ของrename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' $'foo\nbar'
rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' $'foo\nbar'
หากต้องการ.
จับคู่บรรทัดใหม่ให้ใช้s
แฟล็กซึ่งจะสิ้นสุดที่ (ด้วยe
) นั่นคือการเขียนในตอนท้ายแทน/se
/e
rename
นั้นเป็นรหัสผ่านล่วงหน้า อาจดีกว่านี้ แต่คุณอาจต้องการเพิ่มคำแนะนำในการติดตั้งเพื่อให้คำตอบนี้มีค่ามากขึ้น