วิธีการป้องกัน `mv 'จากการย้ายคอลเลกชันของไฟล์ไปเป็นไฟล์เดียว?


17

ฉันเพิ่งสูญเสียคอลเล็กชั่นเสียงไปโดยที่ฉันทำผิดพลาดไป :-(
ดีใจมากฉันมีการสำรองข้อมูลล่าสุดค่อนข้างมาก แต่มันก็ยังน่ารำคาญนอกเหนือจากของคุณอย่างแท้จริงผู้ร้ายคนอื่น ๆ ที่ทำอันตรายmvซึ่งจะแสดงดังต่อไปนี้:

ไฟล์เสียงมีรูปแบบที่แน่นอน:

ARTIST - Some Title YY.mp3

ที่YYเป็นสเปคปี 2 หลัก

mkdir 90<invisible control character>

(จนถึงขณะนี้ฉันไม่ทราบว่าฉันได้พิมพ์อักขระเกินหนึ่งในสามซึ่งมองไม่เห็น ... !)
แทนที่จะมีทั้งหมดในไดเรกทอรีเดียวฉันต้องการมีเพลงทั้งหมดปี 1990 ในไดเรกทอรีเดียว ดังนั้นฉันจึงพิมพ์:

find . -name '* 9?.mp3' -exec mv {} 90 \;

ไม่ยากเลยที่จะเข้าใจว่าเกิดอะไรขึ้นใช่มั้ย : ->
ผลลัพธ์ (หายนะ) คือไดเรกทอรีที่ว่างเปล่าบริสุทธิ์ที่เรียกว่า '90 บางสิ่งบางอย่าง '(มีบางอย่างที่เป็นตัวควบคุม "ที่มองไม่เห็น") และไฟล์เดียวหนึ่งไฟล์ที่เรียกว่า' 90 'เขียนทับnครั้ง

ไฟล์ทั้งหมดหายไป : - (((ชัด)

ความปรารถนาmvจะได้รับการตรวจสอบในเวลาไม่ว่าจะเป็นลายเซ็นของ "ไฟล์" ปลายทาง (จำไว้ใน * NIX: ทุกอย่างคือไฟล์ ) เริ่มต้นด้วยd------(เช่นdrwxr-xr-x) และแน่นอนว่าปลายทางนั้นมีอยู่จริงหรือไม่ มีความแตกต่างจากสถานการณ์ดังกล่าวข้างต้นเมื่อคุณก็ลืมไปmkdirไดเรกทอรีแรก (แต่แน่นอนคุณคิดว่ามันอยู่ที่นั่น ... )

แม้แต่ระบบปฏิบัติการสัตว์เลี้ยงที่เกลียดชังของเราเริ่มต้นด้วยทุนที่Wทำได้ คุณจะได้รับแจ้งให้ระบุประเภทของปลายทาง (ไฟล์? directory?) หากคุณต้องการ

ดังนั้นฉันสงสัยว่าเรา * NIXers ยังคงต้องเขียน " mvscriptlet" เพื่อหลีกเลี่ยงความประหลาดใจที่ไม่พึงประสงค์เหล่านี้


2
ไม่ใช่ว่าไฟล์ทั้งหมดจะหายไป อย่างน้อยหนึ่ง.mp3ควรมีชื่อ90อาจเป็นชื่อที่คุณไม่มีข้อมูลสำรอง
Anthon

2
เฮ้คุณมีอารมณ์ขันแบบเหยียดหยาม :-P นั่นคือไฟล์ที่เรียกว่า "ไฟล์เดียว" ในการพิมพ์ตัวหนาใน OP ของฉัน :)
syntaxerror

2
mvไม่ใช่ปัญหาที่นี่เทคนิคไม่ทราบว่าคุณกำลังย้ายชุดของไฟล์ คุณกำลังเรียกใช้mvหนึ่งครั้งสำหรับแต่ละไฟล์ นั่นเป็นวิธีการfind -exec ;ทำงาน หากคุณเคยใช้find -exec +(เช่นในความคิดเห็นบางส่วน) mv จะกรีดร้องทันทีที่มันมีอาร์กิวเมนต์มากกว่าหนึ่งข้อ
Etan Reisner

แม้ว่าการเรียกใช้mvไฟล์แต่ละไฟล์อาจจะคิดน้อยลงเล็กน้อยในตอนแรกมันจะ (เหมือนที่ฉันเคยกล่าวไว้ก่อนหน้านี้) เป็นทางออกเดียวที่มีสติเมื่อไฟล์ต้นฉบับกระจัดกระจายในไดเรกทอรีย่อยต่างๆ ในกรณีทดสอบของฉันไฟล์ต้นฉบับทั้งหมดในไดเรกทอรีเดียวไม่ได้หมายความว่าเป็นกรณีทดสอบจริงของฉัน อันที่จริงมันเป็นแค่การทำให้เข้าใจง่ายเพราะฉันอาจจะอธิบายอย่างง่าย ๆ ด้วยตัวเองในภายหลัง นอกจากนี้ยังทำให้การอ่านคำถามใช้เวลาน้อยลงเนื่องจากความยาวลดลง :)
syntaxerror

ทำไมคุณคาดหวังmvให้ปลายทางมีอยู่ mv oldfile newfileเป็นวิธีในการเปลี่ยนชื่อไฟล์และมันโง่ที่คาดว่าnewfileจะมีอยู่แล้วและเป็นไดเรกทอรี
Barmar

คำตอบ:


37

คุณสามารถผนวก a /ไปยังปลายทางหากคุณต้องการย้ายไฟล์ไปยังไดเรกทอรี ในกรณีที่ไม่มีไดเรกทอรีคุณจะได้รับข้อผิดพลาด:

mv somefile somedir/
mv: cannot move ‘somefile’ to ‘somedir/’: Not a directory

ในกรณีที่มีไดเรกทอรีอยู่มันจะย้ายไฟล์ไปยังไดเรกทอรีนั้น


4
ขอบคุณมาก! นั่นควรเป็นตัวช่วยชีวิตในอนาคตของฉันในตอนนั้น ฉันเป็นหนี้คุณ (เช่นเดียวกับเพื่อนของฉันทำผิดพลาดเหมือนกันเมื่อหลายปีก่อนดังนั้นฉันรู้สึกว่าฉันไม่ได้อยู่คนเดียว)
ซินแท็กซ์เทอร์เมื่อ

1
นอกจากนี้เมื่อใช้ Shells บางตัวคุณจะมีตัวเลือก Tab เพื่อเติมชื่อไฟล์ให้คุณโดยอัตโนมัติ ถ้าฉันไม่สามารถค่อนข้างจำชื่อไดเรกทอรีและไม่ต้องการยุ่งเหมือนคุณเพิ่งมีเพียงแค่เจาะในตัวละครหรือสองของชื่อไดเรกทอรีและกด Tab จากนั้นคุณสามารถมั่นใจได้ว่ามันมีอยู่เพราะการเติมอัตโนมัติวางไว้ที่นั่น ....
Andyz Smith

@AndyzSmith นั่นคือสิ่งที่ดีมาก คุณอาจเรียกมันว่านิสัยของฉันที่จะใช้ TAB สำหรับไดเรกทอรีหรือเส้นทางที่ซับซ้อนเท่านั้น แต่ไม่ใช่สำหรับตัวอักษร 2 ตัวอักษร :) แต่ลองคิดดูสิ ... บางทีฉันควรจะพิจารณากรณีหลังด้วยเช่นกัน จากนี้ไป.
ไวยากรณ์

20

coreutils GNU แล้วได้ตัวเลือกที่ระบุว่าคุณต้องการที่จะย้ายไปยังไดเรกทอรี:mv / หากไม่มีตัวเลือกอาร์กิวเมนต์จะบ่นแทนการย้ายไฟล์ทั้งหมดของคุณไปยังชื่อไฟล์เดียวกัน-t--target-directorymv

ฉันจะเขียนผู้เสนอญัตติของคุณดังนี้

find . -name '* 9?.mp3' -exec mv -t 90 {} +

สังเกตการใช้งาน+แทนการวน\;ชื่อไฟล์ให้มากที่สุดเท่าที่จะเป็นไปได้ส่งผลให้สามารถประมวลผลได้เร็วขึ้น


ขอบคุณ (หวังว่ามันจะไม่ใช่หนึ่งใน GNU-isms เหล่านั้นอีกแล้ว)
ซินแท็กซ์เทอร์เมื่อ

2
@syntaxerror มันเป็น GNUism เป็นไปได้:find . -name '* 9?.mp3' -exec sh -c 'exec mv "$@" 90/' sh {} +
Stéphane Chazelas

ขอบคุณมากสำหรับซับใน SNEAKY นี้! แค่คิดว่ามันเป็น +5 ฉันให้คุณ :) จะทำการทดลองและข้อผิดพลาดจำนวนมากโดยไม่จำเป็น --- และคุณก็รู้ดีว่าทำไมฉันถึงทำคำพูดนั้น เพียงแค่ต้องอยู่บนเครื่องที่ตรง POSIX (ไม่เกิดขึ้นน้อยเกินไป) และฉันจะมีปัญหาต่อไปที่นั่น :)
syntaxerror

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

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

10

นอกจากนี้หากคุณมักวางแผนที่จะหลีกเลี่ยงการเขียนทับโดยไม่ตั้งใจในอนาคตมีความเป็นตัวเลือกสำหรับการ-i mvโดยส่วนตัวฉันไม่สามารถคิดถึงข้อเสียใด ๆ ได้ถ้าคุณ

alias mv='mv -i'

หากคุณต้องการเขียนทับสิ่งใดสิ่งหนึ่งเพียงแค่ผ่าน-fตัวเลือก

findนามแฝงใช้เวลาเพียงผลถ้าคุณพิมพ์คำสั่งโดยตรงเข้าไปในเปลือกโต้ตอบไม่ได้สำหรับกรณีเช่นการภาวนาโดย คุณสามารถวิ่งได้

find . -name '* 9?.mp3' -exec mv -i {} 90 \;

จากนั้นคุณจะได้รับพร้อมท์หากmvพยายามเขียนทับไฟล์ที่มีอยู่


4
หรือ - ในขณะที่คุณอาจไม่ทราบ - ประเภท '\ mv mv`แทน "เคล็ดลับ" ที่รู้จักกันน้อยกว่านี้จะทำให้คำสั่งที่มีเครื่องหมายแบ็กสแลชต่อท้ายเพื่อละเว้นคำจำกัดความของนามแฝงใด ๆ
ไวยากรณ์

แน่นอนถ้าคุณกำลังพูดถึงจริงๆfind ... -exec mv ...คุณจะต้องสร้าง~/bin/mv(หรือไดเรกทอรีที่เหมาะสมอื่น ๆ ) และทำมัน/bin/mv -i "$@"- เพราะfind ... -execไม่ได้ดูนามแฝง
G-Man กล่าวว่า 'Reinstate Monica'

env mvในกรณีนี้ผมชอบ พิมพ์น้อยลง :) เนื่องจากรูปแบบแป้นพิมพ์ในตัวเครื่องของฉันต้องการให้กดแป้น SHIFT เพื่อไปข้างหน้าเครื่องหมายทับฉันจึงชอบรุ่น "slash-less" เสมอ (ถ้ามี)
ไวยากรณ์

1
@syntaxerror: BTW เมื่อคุณตอบกลับความคิดเห็น (ในความคิดเห็นใหม่) มันเป็นเรื่องธรรมดาที่จะพูดถึงชื่อผู้เขียนนำหน้าด้วย“ @” เช่นเดียวกับใน“ @ G-Man” ด้วยวิธีนี้ฉันจะได้รับแจ้ง (ฉันสามารถตอบความคิดเห็นล่าสุดของคุณได้ในเวลาอันรวดเร็วเพราะฉันได้รับแจ้งจากความคิดเห็นของ Jenny D) คุณสามารถย่อหรือใช้ชื่อเต็ม (ไม่มีช่องว่าง) เช่น "@ StéphaneChazelas" ผู้เขียนโพสต์จะได้รับแจ้งความคิดเห็นโดยอัตโนมัติต่อโพสต์นั้น ดูการตอบกลับในความคิดเห็นย่อหน้าหน้าความช่วยเหลือนี้
G-Man กล่าวว่า 'Reinstate Monica'

1
ฉันขอโทษฉันไม่ได้ใช้อินเทอร์เน็ตเป็นเวลาหนึ่งวัน @ G-Man ฉันยอมรับว่าการมีเวอร์ชันส่วนบุคคลmvในสถานที่ที่จุดเริ่มต้น$PATHจะเป็นวิธีที่สะอาดกว่า ในทางกลับกันฉันมักเกิดmvความประมาทในเชลล์เชิงโต้ตอบ (เพราะมันเกิดขึ้นเร็ว) ในขณะที่ฉันเขียนสิ่งที่ซับซ้อนกว่าเช่นfindหรือforลูปหรือแม้แต่สคริปต์เชลล์ฉันมักจะทำการวิ่งแบบแห้ง (โดยใช้echo) เพื่อให้แน่ใจว่าฉันจะไม่ทำลายบางสิ่ง ในกรณีเหล่านั้นฉันไม่จำเป็นต้องมีมือจับmvเพราะฉันได้ใส่ความคิดลงไปแล้ว
ayekat

7

นอกจากคำตอบที่ดีเลิศข้างต้นฉันต้องการชี้แจงว่าทำไมคุณไม่ได้รับคำถามเกี่ยวกับว่าจะย้ายไฟล์หรือไม่

หากคุณย้ายไฟล์หนึ่งไฟล์ไปที่ชื่อใหม่และชื่อนั้นไม่ใช่ไดเรกทอรีmvจะเปลี่ยนชื่อไฟล์ของคุณเป็นชื่อใหม่

ปัญหาที่นี่คือที่ที่คุณใช้findในการดำเนินการmvครั้งเดียวต่อไฟล์ไม่ได้ครั้งเดียวสำหรับไฟล์ทั้งหมด

หากคุณทำเสร็จmv *90.mp3 90แล้ว mvจะเกิดข้อผิดพลาดว่า "ไฟล์เป้าหมายไม่ใช่ไดเรกทอรี"

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


หากคุณทำเสร็จmv *90.mp3 90แล้ว mv จะล้มเหลวด้วยข้อความแสดงข้อผิดพลาดว่า "ไฟล์เป้าหมายไม่ใช่ไดเรกทอรี" ฮะใช่ทำไมมีความซับซ้อนมากใช่มั้ย ฉันใช้สายของคุณและฉันจะมีความสุข เฉพาะในกรณีเล็กน้อยนี้แม้ว่า :) เพราะนี่เป็นวิธีปกติที่ฉันถามคำถามของฉัน: ฉันจะทำให้พวกมันแคบลงเพราะเห็นแก่ความเรียบง่าย ไม่มีใครคัดค้านfindจนถึงตอนนี้ว่าไฟล์ 90 อาจกระจัดกระจายไปทั่วในไดเรกทอรีย่อยต่างๆซึ่งฉันต้องการ "จับ" เช่นกัน ถ้าเพียง แต่ถ้าพวกเขาเสมอในไดเรกทอรีแหล่งหนึ่งของmvสายมีผลบังคับใช้
ไวยากรณ์

@syntaxerror จริงมาก - ฉันหมายถึงสิ่งนี้เป็นตัวอย่างของการmvทำงานไม่ใช่การวิจารณ์เครื่องมือที่คุณเลือก
เจนนี่ D

1
คุณอาจจะสร้างบางสิ่งบางอย่างที่ผสมผสานfindและmvเช่นfind /music -type d -exec mv {}/*90.mp3 targetdir\;- แต่ตอนนี้ฉันรู้สึกเหมือนฉันกำลังซับซ้อนและใช้-iหรือ-tมีประสิทธิภาพมากขึ้น
Jenny D

1
@ เจนนี่: หากfind . -type d -exec mv {}/*9?.mp3 target \;ตัวอย่างของคุณใช้งานได้อาจมีความเสี่ยงที่mvคำสั่งจะค้นหาmv file targetในแต่ละไดเรกทอรีที่มีเพียง*9?.mp3ไฟล์เดียว ดังนั้นไฟล์ดังกล่าวทั้งหมด (ยกเว้นไฟล์ล่าสุด) จะสูญหาย
G-Man กล่าวว่า 'Reinstate Monica'

4
@syntaxerror: ฉันขอชื่นชมความพยายามของคุณในการเปิดเผยส่วนสำคัญของปัญหาของคุณมากกว่าสคริปต์บรรทัดทั้งหมด 42,000 รายการที่เกิดขึ้น แต่ถึงแม้ว่าคุณไม่ต้องการที่จะทำบางสิ่งบางอย่างให้กับทุก*.mp3ไฟล์ในต้นไม้ไดเรกทอรีคุณสามารถshopt -s globstarแล้วใช้คำสั่งของคุณบน**/*.mp3- The จะทำหน้าที่เหมือน** find
G-Man กล่าวว่า 'Reinstate Monica'

1

ในฐานะกลยุทธ์สำรองทั่วไปฉันขอแนะนำให้เปลี่ยนการทำงานประเภทนี้เป็นสคริปต์ชั่วคราว ฉันชอบที่จะดูผลลัพธ์findและเปลี่ยนมันเป็นmvคำสั่งด้วยมือเพื่อให้แน่ใจว่าฉันเข้าใจสิ่งที่ฉันทำก่อนที่จะดำเนินการ เช่น.

find . -name '* 9?.mp3' > tmp
vim tmp

ตอนนี้ฉันสามารถดูรายชื่อไฟล์และเขียนเนื้อหาไฟล์เป็นคำสั่งเชลล์

  • วางเนื้อหาไฟล์ในหนึ่งบรรทัด: ggVGJ
  • ย่อหน้า: Imv [esc]
  • ผนวก: Asomedir/ [esc]
  • บันทึกไฟล์ อ่านอีกครั้ง หายใจเข้า
  • ดำเนินการsource tmpในบรรทัดคำสั่ง

มันเป็นกลยุทธ์ที่อนุรักษ์นิยม แต่ฉันถูกกัดบ่อยเกินไปด้วยการพิมพ์ผิด-execหรือsedคำสั่งหรือการขยายตัวของเชลล์ที่เข้าใจผิดและฉันชอบที่จะใช้วิธีการที่สอดคล้องกันช้า

ในคำอื่น ๆ : -execฉันขี้ขลาดเกินไปที่จะใช้


1
คุณออกจาก:%s/.*/"&"/ขั้นตอนไปแล้ว - เนื่องจากในกรณีนี้คุณรู้ว่าชื่อไฟล์ทุกไฟล์มีช่องว่างอย่างน้อยหนึ่งช่อง
G-Man กล่าวว่า 'Reinstate Monica'

1
สิ่งนี้จะกัดคุณหากชื่อไฟล์มีช่องว่างหรืออักขระพิเศษอื่น ๆ คุณต้องพูดอย่างถูกต้อง การตรวจสอบรายการคำสั่งไม่น่าจะมีข้อผิดพลาดเป็นพิเศษ มีวิธีที่ดีกว่ามากในการตรวจสอบคำสั่งก่อนที่จะเรียกใช้คำสั่งเช่นเรียกใช้echo mvแทนmvแล้วลบechoหากคุณพอใจ
Gilles 'หยุดความชั่วร้าย'

จำผิดพลาดเช่นชื่อไฟล์ที่มีช่องว่างเป็นสิ่งที่แม่นยำเทคนิคนี้จะช่วยให้มี :-)
ทอมรีส์

0

ตัวเลือกอื่น:

-n, - ไม่อุดตันไม่เขียนทับไฟล์ที่มีอยู่

มันเหมือนกับ -i แต่มันจะไม่ถามมันจะล้มเหลว

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