'เปลี่ยนชื่อ' และ 'mv' ต่างกันอย่างไร


12

มันไม่ชัดเจนสำหรับฉัน แต่อะไรคือความแตกต่างระหว่างmvและrename(จากutil-linux-ng 2.17.2เมื่อ/usr/bin/rename) มีข้อดีมากกว่าข้ออื่นที่renameยอมรับการแสดงออกปกติmvหรือไม่ ฉันเชื่อว่าrenameสามารถจัดการเปลี่ยนชื่อไฟล์หลายรายการพร้อมกันในขณะที่mvไม่ทำเช่นนี้

ฉันไม่พบข้อบ่งชี้ที่ชัดเจนในmanหน้าเว็บของพวกเขาสิ่งอื่นจะแยกพวกเขาออกจากกันหรือผ่านการสอบสวนด้วยตัวเอง


2
มาทำให้แน่ใจว่าเรากำลังพูดถึงสิ่งเดียวกัน ผลลัพธ์จากtype -a renameและrename --versionคืออะไร
Jeff Schaller

@JeffSchaller มันมีความอยากรู้อยากเห็นมากกว่าในส่วนของฉัน แต่ในหนึ่งในเครื่อง * ของฉันที่ฉันได้รับrename is /usr/bin/renameและrename (util-linux-ng 2.17.2)ตามลำดับ
Urda

6
มีการเปลี่ยนชื่อที่แตกต่างกันออกไปเล็กน้อยและอาจเป็นนามแฝง / ฟังก์ชั่น / สคริปต์ดังนั้นฉันแค่อยากให้แน่ใจว่าเรารู้ว่ามันคืออะไร ขอขอบคุณ! โปรดแก้ไขผลลัพธ์เหล่านั้นในคำถามของคุณ
Jeff Schaller

@JeffSchaller ไม่ต้องกังวลจริง ๆ แล้วลิงก์นี้เป็นลิงค์เดียวที่ฉันเพิ่งค้นพบที่แสดงให้ฉันเห็นว่าrenameอาจมีความหมายที่แตกต่างกันในความแตกต่าง
Urda

5
ดูเหมือนว่าคำถามของคุณจะมีคำตอบ “ อะไรคือความแตกต่างระหว่างเจ็ทกับรถสามล้อนอกเหนือจากข้อเท็จจริงที่เจ็ตสามารถบินได้และเร็วกว่าหลายพันเท่า” :-) ⁠
G-Man กล่าวว่า 'Reinstate Monica'

คำตอบ:


21

มันเป็นสิ่งที่บอกไว้บนฝาสำหรับทั้งคู่

mvเป็นยูทิลิตี้มาตรฐานเพื่อย้ายไฟล์หนึ่งไฟล์ขึ้นไปไปยังเป้าหมายที่กำหนด มันสามารถใช้ในการเปลี่ยนชื่อไฟล์หากมีเพียงหนึ่งไฟล์ที่จะย้าย หากมีหลายรายการmvจะใช้ได้ก็ต่อเมื่อเป้าหมายคือไดเรกทอรีและย้ายไฟล์ไปที่นั่น

ดังนั้นmv foo barจะย้ายไฟล์fooไปยังไดเรกทอรีbar(หากมีอยู่) หรือเปลี่ยนชื่อfooเป็นbar(หากbarไม่มีอยู่หรือไม่ใช่ไดเรกทอรี) mv foo1 foo2 barจะย้ายไฟล์ทั้งสองไปยังไดเรกทอรีbarหรือบ่นหากbarไม่ใช่ไดเรกทอรี

mvจะเรียกใช้rename()ฟังก์ชั่นไลบรารี่ C เพื่อย้ายไฟล์และถ้ามันไม่ทำงาน (พวกมันถูกย้ายไปยังระบบไฟล์อื่น) มันจะคัดลอกไฟล์และลบต้นฉบับ

หากคุณมีmvและคุณต้องการเปลี่ยนชื่อไฟล์หลายไฟล์คุณจะต้องใช้เชลล์ลูป มีจำนวนของคำถามเกี่ยวกับที่นี่ในเว็บไซต์ที่มีให้ดูเช่นนี้ , นี้ , และอื่น ๆ


ในทางกลับกันrenameยูทิลิตี้ต่างๆจะเปลี่ยนชื่อไฟล์แยกกัน

renameจาก util ลินุกซ์ที่คุณพูดถึงทำให้เปลี่ยนตัวสตริงง่ายเช่นrename foo bar *จะเปลี่ยนfoobarไปbarbarและจะasdffoo อย่างไรก็ตามมันไม่ได้ใช้การแสดงออกปกติ!asdfbar

ยูทิลิตี้เปลี่ยนชื่อ Perl ( หรืออินสแตนซ์ต่างๆของมัน ) ใช้เวลาในการแสดงออก Perl เพื่อเปลี่ยนชื่อไฟล์ หนึ่งมักจะใช้คำสั่งที่รูปแบบคือการแสดงออกปกติs/pattern/replacement/

ทั้งการเปลี่ยนชื่อ util-linux และการเปลี่ยนชื่อ Perl สามารถใช้เพื่อย้ายไฟล์ไปยังไดเรกทอรีอื่นในเวลาเดียวกันโดยทำการเปลี่ยนแปลงที่เหมาะสมกับชื่อไฟล์ แต่มันค่อนข้างน่าอึดอัดใจ ไม่มีการเรียกมากกว่าการเรียกrename()ไฟล์ดังนั้นการย้ายจากระบบไฟล์หนึ่งไปยังอีกระบบหนึ่งจะไม่ทำงาน

ตามที่renameคุณมีมันอาจขึ้นอยู่กับการกระจายของคุณและ / หรือสิ่งที่คุณติดตั้ง ส่วนใหญ่สนับสนุนrename --versionดังนั้นใช้เพื่อระบุว่าคุณมี


ไม่เพียง 'การแสดงออกปกติ' แต่ทำงานได้ถ้าต้องการ
Gilles Quenot

@GillesQuenot ใช่คุณสามารถทำเช่นrename '$_=lc' *กับชื่อไฟล์ตัวพิมพ์เล็ก แต่ฉันคิดว่ากรณีที่พบบ่อยที่สุดคือการใช้s///(ซึ่งฉันพูดถึง) และส่วนรูปแบบของมันคือ regex; ฉันไม่คิดว่าคุณสามารถใช้ฟังก์ชั่นที่นั่นได้ คุณสามารถทำได้ในส่วนทดแทน
ilkkachu

@ MyWrathAcademia ตัวอย่างแรกใน man page นั้นเหมาะกับฉัน (มันแค่ทำสิ่งที่แตกต่างจากอีกอัน) นอกจากนี้เหตุผลที่ฉันเชื่อมโยงกับหน้าเว็บของ Debian ก็คืออย่างน้อยก็มีความชัดเจนมากว่าหน้า man นั้น rename.ulเป็นและจะเป็นรุ่น util-linux ไม่ใช่สำหรับคนอื่น ๆ
ilkkachu

@ilkkachu คุณคิดที่จะเพิ่มคำอธิบายลงในตัวอย่างแรกนั้นทั้งในคำตอบของคุณหรือในความคิดเห็น มันแตกต่างจากตัวอย่างในman renameดังนั้นจึงเป็นการดีที่จะทราบความเข้าใจของคุณเกี่ยวกับตัวอย่าง debian
MyWrathAcademia

@ MyWrathAcademia ฉันคิดว่าคุณหมายถึงrename foo foo0 foo?; rename foo foo0 foo??ตัวอย่างเนื่องจากนั่นเป็นความแตกต่างเพียงอย่างเดียวระหว่างสองหน้าเว็บที่ฉันเห็น คู่ของคำสั่งนั้นใช้งานได้เพราะคำสั่งแรกเพิ่มศูนย์ให้กับชื่อของชื่อไฟล์แต่ละหลักเดียวและหลังจากนั้นคำสั่งที่สองจะเพิ่ม (อีก) ศูนย์ในแต่ละชื่อไฟล์สองหลัก ชุดที่สองนั้นรวมถึงไฟล์ที่ถูกเปลี่ยนชื่อโดยคำสั่งแรก เมื่อใช้rename foo foo00 foo?เป็นคำสั่งแรกก็ใช้งานได้เพียงเพิ่มสองศูนย์ในครั้งเดียว
ilkkachu

2

mvเพียงเปลี่ยนชื่อของไฟล์ (มันสามารถย้ายไปยังระบบไฟล์หรือพา ธ อื่นได้) คุณให้ชื่อเก่าและชื่อใหม่และเปลี่ยนไฟล์เป็นชื่อหรือที่ตั้งใหม่ renameถูกใช้เพื่อทำการเปลี่ยนแปลงการตั้งชื่อจำนวนมาก สมมติว่าคุณมีพันไฟล์foo000.logผ่านfoo999.logและคุณอยากจะเปลี่ยนให้พวกเขาผ่านbar000.log bar999.logด้วยการmvที่คุณจะต้องทำmv foo000.log bar000.log, mv foo001 bar001.logฯลฯ หรืออื่น ๆ ที่เขียนสคริปต์ เมื่อrenameคุณทำrename foo bar foo*.logแล้ว voila ไฟล์นับพันจะถูกเปลี่ยนในทันที! สวยเท่ห์ ตรวจสอบman renameหน้าอีกครั้งเพื่อดูรายละเอียด


2

mv

มันเป็นบรรทัดคำสั่งขั้นพื้นฐานที่ออกแบบมาเพื่อทำสิ่งหนึ่งและทำมันได้ดี (Unix ปรัชญา): ไฟล์ย้าย (s) หรือ directorie (s)

คุณสามารถแฮ็คSTDOUT& STDINเพื่อแก้ไขสตริงปลายทางได้ทันที แต่ไม่ใช่แฮ็คอัจฉริยะ

เปลี่ยนชื่อ (หนึ่งของ Perl)

คำเตือน มีเครื่องมืออื่น ๆ ที่มีชื่อเดียวกันซึ่งอาจหรืออาจจะไม่สามารถทำได้ดังนั้นควรระมัดระวัง

เมื่อผู้คนพูดถึงrenameเราคิดเกี่ยวกับสิ่งนี้ไม่ใช่ELFคนที่มีพลังน้อยกว่า (เวทมนตร์?)

มันไม่ธรรมดามันเป็น Perl คุณสามารถผ่านฟังก์ชั่นของ Perl ได้และมันก็มีประสิทธิภาพมาก

ลองพิจารณาตัวอย่างนี้:

คุณต้องการเปลี่ยนชื่อกลุ่มไฟล์เช่น

foobar_1.txt
foobar_2.txt
foobar_3.txt

คุณสามารถเพิ่มค่าศูนย์เป็นตัวเลขด้วยsprintf()เช่นนี้ (โดยใช้ regex, heh, มันคือ Perl: D):

rename 's/(\d+)/sprintf("%04d", $1)/e' foobar_*.txt

ตอนนี้คุณมี:

foobar_0001.txt
foobar_0002.txt
foobar_0003.txt

ไม่ใช่คำสั่งพื้นฐานจริงๆเหรอ?

ไม่ได้ออกแบบมาเพื่อย้าย dirแต่สามารถทำได้:

$ mkdir -p /tmp/foo/bar/base
$ touch /tmp/foo/bar/base/file
$ rename 's!/tmp/foo/bar/base/file!/tmp/file!' /tmp/foo/bar/base/file

ไฟล์ที่ถูกย้าย

/tmp/file

code บางรหัสที่เราเห็นใน*.stackexchange.*เว็บไซต์

ป้อนคำอธิบายรูปภาพที่นี่

for FILE in `ls *.txt`
do
    mv ${FILE} `echo ${FILE} | sed 's/anything_ugly/anything_still_ugly/'`
done

มันไม่ใช่วิธีที่จะไปมันเป็นรถธรรมดาเพียงเพื่ออธิบายว่าทำไมต้องใช้เครื่องมือที่ถูกต้องในเวลาที่เหมาะสม


+1 สำหรับsprintfไอเอ็นจีที่มีการเปลี่ยนชื่อ
Archemar

-1

mvย้ายหรือเปลี่ยนชื่อไฟล์และไดเรกทอรีและจะสำรองข้อมูล; เปลี่ยนชื่อเพียงแค่เปลี่ยนชื่อไฟล์

mvมีความสามารถและตัวเลือกเพิ่มเติม ดูสวิตช์ในหน้าคู่มือสำหรับแต่ละคนเพื่อดูความแตกต่างในความสามารถ มาดูการใช้คนใน Ubuntu 18.04LTS (ระยะของคุณอาจแตกต่างกันไปขึ้นอยู่กับเวอร์ชั่นของแต่ละแพ็คเกจ):

ตัวเลือก mv (ไม่ใช้ความช่วยเหลือและรุ่น)

   --backup[=CONTROL]  
          make a backup of each existing destination file  

   -b     like --backup but does not accept an argument  

   -f, --force  
          do not prompt before overwriting  

   -i, --interactive  
          prompt before overwrite  

   -n, --no-clobber  
          do not overwrite an existing file  

  If you specify more than one of -i, -f, -n, only the final one takes effect.  

   --strip-trailing-slashes  
          remove any trailing slashes from each SOURCE argument  

   -S, --suffix=SUFFIX  
          override the usual backup suffix  

   -t, --target-directory=DIRECTORY  
          move all SOURCE arguments into DIRECTORY  

   -T, --no-target-directory  
          treat DEST as a normal file  

   -u, --update  
          move only when the SOURCE file is newer than the destination file or when the destination file is missing  

   -v, --verbose  
          explain what is being done  

   -Z, --context  
          set SELinux security context of destination file to default type  

ตัวเลือกการเปลี่ยนชื่อ (ไม่ให้ความช่วยเหลือและรุ่น)

   -s, --symlink   
          Do not rename a symlink but its target.  

   -v, --verbose  
          Show which files where renamed, if any.  

   -n, --no-act  
          Do not make any changes.  

   -o, --no-overwrite  
          Do not overwrite existing files.            

3
กำหนด 'มีประสิทธิภาพมากขึ้น' mv รองรับ regex เช่นเปลี่ยนชื่อหรือไม่
Gilles Quenot

ตามที่ผู้ถามระบุว่าไม่มี
K7AAY

2
ว้าวช่างเถียงอะไรกัน
Gilles Quenot

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