รายการยกเว้น mv บรรทัดคำสั่ง


11

มีวิธีการmv, cpหรือการดำเนินการใด ๆ เช่นไฟล์ที่ฉันสามารถระบุไฟล์ทั้งหมดที่ฉันไม่ต้องการได้รับผลกระทบ?

ตัวอย่างเช่นสมมติว่าผมมีโฟลเดอร์ที่มีไฟล์ที่file1, file2และfile3และฉันต้องการที่จะย้ายfile1และfile2ที่ไหนสักแห่ง แทนที่จะตั้งชื่อไฟล์ที่จะย้าย ( mv file1 file2 /path/to/destination) อย่างชัดเจนฉันต้องการตั้งชื่อไฟล์ที่จะไม่ย้ายและให้ไฟล์อื่น ๆ ทั้งหมดในโฟลเดอร์ถูกย้าย ( mv --some-switch file3 /path/to/destination)


ฉันเชื่อว่าmv file1 file2 /path/to/destinationจะไม่ทำในสิ่งที่คุณต้องการให้ทำ
phunehehe

คำตอบ:


19
  • คุณสามารถใช้รูปแบบการวนรอบขั้นสูงในบางเชลล์เพื่อจับคู่ไฟล์ทั้งหมดในไดเรกทอรียกเว้นการจับคู่รูปแบบเฉพาะ ตัวอย่างเช่นในคำสั่ง ksh, bash หรือ zsh

    shopt -s extglob   ## needed in bash only
    setopt ksh_glob   ## needed in zsh only
    mv /source/!(*.bak) /destination
    

    จะย้ายไฟล์ทั้งหมดใน/sourceการยกเว้นสำหรับการจับคู่ไฟล์/destination *.bakใน zsh คุณยังสามารถเขียนได้/source/^*.bakหากคุณเรียกใช้ครั้งแรกsetopt extended_globและโดยทั่วไป (ต้องมีอีกครั้งsetopt extended_glob) /source/*~*.bak(หรือ/source/a*~*.bakสำหรับไฟล์ทั้งหมดที่มีชื่อขึ้นต้นด้วยaยกเว้น.bakไฟล์ ฯลฯ )

  • Zsh มีคำสั่งคัดลอก / ย้าย / เชื่อมโยงจำนวนมากซึ่งสามารถใช้เพื่อย้ายไฟล์ทั้งหมดยกเว้นไฟล์ที่ตรงกับรูปแบบ ตัวอย่างเช่นคำสั่งต่อไปนี้จะย้ายไฟล์ทั้งหมดยกเว้น*.bakจาก/sourceถึงtargetและเพิ่ม.bakลงในชื่อไฟล์ในกระบวนการ:

    autoload zmv
    zmv '/source/(*)~*.bak' '/target/$1.bak'
    
  • มีหลายคำสั่งที่เรียกว่าrenameลอยอยู่รอบ ๆ บน Debian และ Ubuntu /usr/bin/renameเป็นสคริปต์ Perl ที่ย้ายไฟล์ไปยังชื่อใหม่ที่สร้างโดยนิพจน์ Perl คุณสามารถยกเว้นไฟล์จากการเปลี่ยนชื่อโดยไม่สร้างชื่อใหม่หากไฟล์นั้นจะถูกยกเว้น ตัวอย่างเช่นคำสั่งต่อไปนี้ (ใช้renameโปรแกรมนี้โดยเฉพาะ) ย้ายไฟล์ทั้งหมดยกเว้น*.bakจาก/sourceเป็น/target:

    rename 's!/source!/target! unless m!\.bak$!' /source/*
    
  • คุณสามารถใช้findคำสั่งเพื่อเลือกไฟล์ที่คุณต้องการย้าย ตัวอย่างเช่นคำสั่งต่อไปนี้จะย้ายไฟล์ปกติทั้งหมดยกเว้น*.bakใน/sourceหรือไดเรกทอรีย่อยเข้า/target(โปรดทราบว่าโครงสร้างไดเรกทอรีถูกยุบ):

    find /source -type f \! -name '*.bak' -exec mv {} /target/ \;
    

    หรือ (มีประสิทธิภาพมากขึ้นหากมีไฟล์จำนวนมากที่จะย้าย)

    find /source -type f \! -name '*.bak' -exec sh -c 'mv "$@" "$0"' /target/ {} +
    
  • rsyncเป็นลักษณะทั่วไปcpและscpมีกฎการรวม / ไม่รวมที่มีประสิทธิภาพมาก ตัวอย่างเช่นคำสั่งดังต่อไปนี้คัดลอกไฟล์ทั้งหมดยกเว้น*.bakใน/sourceหรือไดเรกทอรีย่อยเข้า/targetเคารพโครงสร้างไดเรกทอรี:

    rsync -a --exclude '*.bak' /source/ /target/
    
  • paxคือ (เหนือสิ่งอื่นใด) cpในสเตียรอยด์ กฎการยกเว้นของมันไม่ได้มีประสิทธิภาพเทียบเท่ากับ rsync แต่ก็มีความสามารถเพิ่มเติมในการเปลี่ยนชื่อไฟล์เมื่อมีการคัดลอก หากคุณเปลี่ยนชื่อไฟล์เป็นสตริงว่างเปล่ามันจะถูกแยกออกจากสำเนา ตัวอย่างเช่นคำสั่งต่อไปนี้คัดลอกไฟล์ทั้งหมดยกเว้น*.bakใน/sourceหรือไดเรกทอรีย่อยลงใน/targetและเปลี่ยนชื่อไฟล์เป็น.bakในการผ่าน

    cd /source && pax -rw -pp -s '/.*\.bak$//' -s '/$/.bak/' . /target/
    

    ตัวอย่างข้างต้นมีผลข้างเคียงที่โชคร้ายของการสร้างไดเรกทอรีfoo.bakที่สามารถหลีกเลี่ยงได้โดยการรวมfindกับpax:

    { cd /source && find . -type f; } | \
    pax -rw -pp -s '/.*\.bak$//' -s '/$/.bak/' /target/
    

น่ากลัว การแก้ไขที่เป็นไปได้หนึ่งอย่าง: ฉันคิดว่าfindคำสั่งต้องจบลงด้วย\;
Steven D

@Steven: ขอบคุณฉันให้ลืมคุณสามารถใช้ทันทีดังต่อไปนี้+ {}
Gilles 'หยุดชั่วร้าย'

รายการที่ดีขอบคุณสำหรับการที่ :-)
echox

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