วิธีการย้ายไฟล์ทั้งหมดจากไดเรกทอรีปัจจุบันไปยังไดเรกทอรีบน?


133

วิธีการย้ายไฟล์ทั้งหมดจากไดเรกทอรีปัจจุบันไปยังไดเรกทอรีบนใน linux?

ฉันลองอะไรที่ชอบmv *.*แต่ก็ไม่ได้ผล


ฉันมีตัวแทนไม่เพียงพอที่จะถามคำถามซ้ำ แต่ฉันขอแนะนำ[linux] [mv] [cwd] [files]หรือสิ่งที่คล้ายกัน
Stephan202

ฉันได้ retagged คำถามนี้ตามคำขอของ Stephan202
eleven81

คำตอบ:


202

คำสั่งที่คุณกำลังมองหาคือ

mv * .[^.]* ..

หรือ (ดูข้อมูลเพิ่มเติมด้านล่าง):

(shopt -s dotglob; mv -- * ..)

คำอธิบาย: mvคำสั่งย้ายไฟล์และไดเร็กทอรี อาร์กิวเมนต์สุดท้ายที่mvเป็นเป้าหมาย (ในกรณีนี้คือไดเรกทอรีหนึ่งขั้นตอน "up" ในแผนผัง, ..) ข้อโต้แย้งก่อนหน้านั้นคือไฟล์ต้นฉบับและไดเรกทอรี เครื่องหมายดอกจัน ( *) เป็นสัญลักษณ์แทนซึ่งตรงกับไฟล์ทั้งหมดที่ไม่ได้ขึ้นต้นด้วยจุด ไฟล์ที่ขึ้นต้นด้วย dot (dotfiles) คือ "hidden" พวกเขาจับคู่โดยใช้รูปแบบ.[^.]*(ดูการแก้ไขด้านล่าง)

ดู manpage mvที่ฉันเชื่อมโยงสำหรับข้อมูลเพิ่มเติมเกี่ยวกับ


ทำไม.[^.]*แทน.*?

ขณะที่คริสจอห์นสันได้อย่างถูกต้องชี้ให้เห็น: รูปแบบ.*นอกจากนี้ยังตรงและ. ..เนื่องจากคุณไม่ต้องการที่จะ (และไม่สามารถ) ย้ายเหล่านั้นดีกว่าที่จะใช้รูปแบบที่ตรงกับชื่อไฟล์ใด ๆ ที่เริ่มต้นด้วยจุดที่ยกเว้นที่สอง รูปแบบ.[^.]*ทำเช่นนั้น: มันตรงกับชื่อไฟล์ใด ๆ (1) ที่ขึ้นต้นด้วยจุด (2) ตามด้วยตัวละครที่ไม่ใช่จุด (3) ตามด้วยอักขระศูนย์หรือมากกว่านั้น

เมื่อPaggas ชี้ให้เห็นเราจำเป็นต้องเพิ่มรูปแบบ.??*เพื่อให้ตรงกับไฟล์ที่ขึ้นต้นด้วยสองจุด findดูคำตอบของเขาเพื่อแก้ปัญหาทางเลือกใช้

คำตอบของ Arjan กล่าวถึงshoptเพื่อหลีกเลี่ยงปัญหาทั้งหมดที่มีกับ dotfiles แต่ก็ยังมีปัญหากับไฟล์ที่เริ่มต้นด้วยเส้นประ และมันต้องใช้สามคำสั่ง ยังฉันชอบความคิด ฉันเสนอที่จะใช้มันเช่นนี้

(shopt -s dotglob; mv -- * ..)

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


7
ใช้.*อาจก่อให้เกิดmvการผลิตคำเตือน / ข้อผิดพลาดเกี่ยวกับการที่จะไม่สามารถที่จะย้ายและ. ..คุณอาจลองmv * .[^.]* ..แทน
คริสจอห์นสัน

1
@alain: ยินดีต้อนรับและยินดีต้อนรับสู่เว็บไซต์! (ถ้า (และถ้ามี) อย่างใดอย่างหนึ่งของโพสต์ที่นี่พอตอบคำถามของคุณแล้วคุณสามารถทำเครื่องหมายว่าเป็นเช่นนั้นจะได้รับโปสเตอร์ 15 คะแนนชื่อเสียงพิเศษและยังให้คุณ 2 ตัวแทนพิเศษ..)
Stephan202

ผมชอบวิธีการแก้ปัญหา shopt ที่ทำงานอยู่ใน subshell A :)
Paggas

2
ไม่มีอันตรายใด ๆ ในไวยากรณ์ *. * - รวมถึง .. เป็นอันตรายเมื่อใช้กับ chmod และ chown และแฟล็ก "recurse" เช่น chmod -R หรือ chown -R และในกรณีที่ผู้ที่ไม่เคยเคยพิมพ์ chown * * * * * * * * หรือ chmod -.. chown ไดเรกทอรีบนในเส้นทางที่คุณกำลังมองหาและใช้ -h (ไม่ปฏิบัติตามการเชื่อมโยงสัญลักษณ์) แต่ mv .. ก็ไม่ทำอะไรเลยไม่ต้องกังวลไป
chris

1
ที่ถูกต้องสามรูปแบบมี*, และ.[^.]* ..?*อาจเป็นครั้งที่สอง .[!.]*สำหรับเชลล์ (POSIX) รุ่นเก่า อ่านเพิ่มเติม

42

คำตอบสั้น ๆ : ใช้

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

คำตอบยาว:

คำสั่ง

mv * .* ..

จะไม่ทำงานเนื่องจาก.*สามารถจับคู่และ. ..แต่คำสั่ง

mv * .[^.]* ..

จะไม่ทำงานเนื่องจาก.[^.]*จะไม่ตรงกันเช่น..filename! แต่สิ่งที่ฉันทำคือ

mv * .[^.] .??* ..

ซึ่งจะตรงกับทุกอย่างยกเว้นและ. จะตรงกับทุกอย่างที่ไม่ได้เริ่มต้นด้วย, จะตรงกับชื่อไฟล์ทั้งหมด 2 ตัวละครเริ่มต้นด้วยจุดยกเว้นและจะตรงกับชื่อไฟล์ทั้งหมดที่เริ่มต้นด้วยจุดที่มีอย่างน้อย 3 ตัวอักษร..*..[^.]...??*

ดีกว่าคุณสามารถใช้

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

ซึ่งหลีกเลี่ยง glob hacks น่าเกลียดในmv * .[^.] .??* ..!


1
นอกจากนี้ฉันลืมที่จะทราบถึงความสำคัญของ - เพื่อให้คำสั่งทำงานอย่างถูกต้องกับชื่อไฟล์ที่ขึ้นต้นด้วยเส้นประ ฉันได้รวม - ในคำตอบการค้นหาของฉันแม้ว่า คำตอบที่สมบูรณ์มากขึ้นโดยใช้ globs คือ "mv - *. [^.]. ?? * .. "
Paggas

+1: ฉันกลับมาเพื่อเพิ่ม..?*ความคิดเห็นของฉันและคุณได้รับการดูแลแล้ว
344 Chris

1
มีอะไรผิดปกติกับการพยายาม mv .. ? มันไม่ทำอะไรเลยและทำอะไรไม่ได้เลย มีคำสั่งอื่น ๆ ที่สามารถทำบางสิ่งได้ (chmod และ chown) แต่ mv และ rm ไม่ทำอะไรเลย หรือ ..
คริส

1
สิ่งนี้จะให้ mv: ตัวเลือกที่ผิดกฎหมาย - t
pal4life

1
Bono เครื่องหมายขีดคั่นคู่บอกmvให้หยุดมองหาตัวเลือกคำสั่งเพิ่มเติม วงเล็บปีกกาเป็นชื่อไฟล์ที่เกิดขึ้น เครื่องหมายบวกบอกว่าแทนที่จะเรียกใช้ exec ต่อผลลัพธ์ (เช่น. ต่อชื่อไฟล์) ใส่ผลลัพธ์มากที่สุดในการประมวลผลเดียวเท่าที่จะทำได้ เพื่อความสมบูรณ์-t..บอกให้ย้ายปลายทางเป้าหมายเพื่อย้ายไฟล์เหล่านี้ทั้งหมดไปที่
isuldor

14

เพียงเพื่อประโยชน์ของความสมบูรณ์หนึ่งสามารถบอก Bash shell ให้รวมไฟล์ที่ซ่อนอยู่โดยใช้shopt:

shopt -s dotglob
mv -- * ..
shopt -u dotglob

+1 ทำความสะอาดมาก ฉันคิดว่าการปรับปรุงเล็กน้อยเป็นไปตามลำดับแม้ว่า ดูการอัปเดตคำตอบของฉัน
Stephan202

8

mv ไม่มีฟังก์ชั่นในการย้ายไฟล์ที่ซ่อนอยู่เมื่อใช้งาน*- ทำไมคุณไม่ใช้ copy แทนล่ะ?

cp -rf . ..

rm -rf *

ไม่จำเป็นต้องเข้าสู่โซลูชันที่ซับซ้อนของ dotglobbing และใช้คำสั่ง find


คำเตือนหากคุณย้ายในระบบไฟล์เดียวกันส่วนใหญ่ของกรณีที่คุณไม่ได้คัดลอกไฟล์จริงๆ แต่เพียงอัปเดตรายการไดเรกทอรีโดยไม่ย้าย inode หรือเนื้อหาไฟล์ ดูแม้กระทั่ง[1 ] ด้วยcpและrmคุณจะคัดลอกทั้งหมดจริงๆ
Hastur

6
rsync -a --remove-source-files . ..

rsync เป็นเครื่องมือคัดลอกไฟล์ที่มีประสิทธิภาพอย่างมากโดยทั่วไปใช้สำหรับการสำรองข้อมูลระยะไกลและมิเรอร์ที่มีประสิทธิภาพ

ด้วยคำสั่งข้างต้นเรากำลังบอกrsyncให้คัดลอกเนื้อหาของ.ลงใน..

สวิตช์เปิด-aใช้งานการเรียกซ้ำไปยัง.ไดเรกทอรีย่อยและเปิดใช้งานตัวเลือกทั่วไปอื่น ๆ

สวิตช์--remove-source-filesบอก rsync ให้ลบไฟล์ต้นฉบับหลังจากทำสำเนาสำเร็จนั่นคือทำให้ rsync ทำงานคล้ายกับmvคำสั่ง


1
คำอธิบายเพิ่มเติมเล็กน้อยน่าจะดี
ChrisF

แน่นอนว่าหวังว่าจะชัดเจนขึ้นในขณะนี้
mrucci

โปรดทราบว่า--remove-source-filesจะไม่ลบไดเรกทอรี (ทำข้อมูลให้ตรงกัน)
Dennis

วิธีการแก้ปัญหาที่ดีที่ยอมรับได้ทำให้ฉันมี-bash: /bin/mv: Argument list too longข้อผิดพลาด อันนี้ใช้งานได้อย่างมีเสน่ห์
userlond

2

ในที่สุดความพยายามmv .จะล้มเหลวเนื่องจาก mv ไม่สามารถยกเลิกการเชื่อมโยงไดเรกทอรีที่คุณอยู่ในปัจจุบันคุณสามารถmv * ..ย้ายไฟล์ใน cwd ได้


2
mv * .??* ../.

*รับไฟล์ที่ไม่ใช่จุดทั้งหมด .??*ได้รับทั้งหมด ไฟล์อย่างน้อยสามไบต์ซึ่งใช้ได้กับไฟล์ที่ถูกต้องทั้งหมด สิ่งใดที่เหลือคุณอาจต้องการrmมากกว่าmvอยู่แล้ว

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


2
คุณอาจจะเพิ่มที่จะได้รับไฟล์หน้าปกเหมือน.[^.] .a
344 Chris

ไม่มีความแตกต่างระหว่าง ../ และ ../ ดังนั้นฉันจะไม่รบกวนการพิมพ์ หลังจากเฉือน นอกจากนี้ในกรณีของ mv และ rm จะไม่มีอันตรายใด ๆ ที่จะรวม และ .. ในรายการนั่นคือไม่มีอะไรน่ากลัวหรือผิดกับ mv *. * / path / to / file /, เช่นเดียวกับ rm หรือแม้กระทั่ง -rf ไม่ทำอะไรเลย
chris

2

คำสั่งที่ย่อเล็กสุดนี้ทำงานบนเชลล์ที่ทันสมัยที่สุด:

\mv -- {,.{[^.],??}}* ..

อย่างอื่นที่กล่าวถึงเป็นวิธีแก้ปัญหาแบบพกพา:

\mv -- * .[^.] .??* ..

คุณสมบัติ:

  1. \ ป้องกันนามแฝงจากการแก้ไข mv อย่างที่ไม่ต้องการ

  2. - ป้องกันชื่อไฟล์ที่มีเครื่องหมายขีดคั่น (-xyz) นำหน้าจากการตีความเป็นอาร์กิวเมนต์บรรทัดคำสั่ง

  3. . [^.] จับคู่ชื่อไฟล์ทั้งสองตัวที่ขึ้นต้นด้วย ยกเว้น ..

  4. . ?? * ตรงกับชื่อไฟล์อื่น ๆ ทั้งหมดสามตัวละครหรือนานกว่า

การใช้งานไร้เดียงสา:

  1. ต่อไปนี้ข้ามชื่อไฟล์ UNIX ที่ซ่อนอยู่ซึ่งเริ่มต้นด้วย (.bashrc)

    mv * ..
    
  2. การจับคู่ต่อไปนี้ .. ซึ่งจะพยายามย้ายทุก ๆ ไดเรกทอรีในที่สุดตลอดทางกลับไปยัง / เข้าสู่ .. ของไดเรกทอรีการทำงานปัจจุบัน ($ PWD หรือ pwd) ห้ามใช้

    mv .* ..
    

2

มันถูกต้องมากขึ้นในการใช้รูปแบบ* .[!.] .??*มากกว่า* .[^.] .??*เดิมที่จะใช้งานกับเชลล์รุ่นเก่าเช่น ksh88:

mv -- * .[!.] .??* ..
  • -- ป้องกันปัญหาเมื่อคุณมีชื่อไฟล์ที่ขึ้นต้นด้วย -
  • * ตรงกับชื่อไฟล์ทั้งหมดที่ไม่ได้ขึ้นต้นด้วย .
  • ไม่มีชื่อไฟล์อักขระหนึ่งตัวที่ขึ้นต้นด้วยชื่อ.ที่คุณสามารถ / ควรย้าย
  • .[!.] ตรงกับชื่อไฟล์อักขระทั้งสองซึ่งเริ่มต้นด้วย .
  • .??* ตรงกับชื่อไฟล์อักขระทั้งสาม (หรือมากกว่า) ซึ่งเริ่มต้นด้วย .

ด้วย ksh88 รูปแบบชื่อไฟล์.[^.]จะตรงกับชื่อไฟล์..(ซึ่งมีอยู่เสมอ) และ.^(ซึ่งอาจไม่มีอยู่) ซึ่งมีผลตรงข้ามกับสิ่งที่ต้องการ


0

ค้นหาและ grep ก็ทำงานเช่นกัน โครงสร้างชนิดนี้อาจมีประโยชน์หากคุณต้องการเลือกไฟล์ตามเกณฑ์ที่ซับซ้อนมากขึ้นโดยการแก้ไข find และ egrep

find -maxdepth 1 | egrep '^./.'         # Returns all files

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..

0

ฉันคิดว่าทางออกที่ง่ายที่สุดสำหรับการย้ายไฟล์ทั้งหมดไปยัง dir หลัก อยากจะเป็น

mv "`ls`" ../

หรือหากมีไฟล์ / ไดเรกทอรีที่ซ่อนอยู่

ใช้:

mv "`ls -a`" ../ 2>/dev/null

นอกจากนี้สมมติว่าคุณต้องการย้ายเนื้อหาของบางโฟลเดอร์ไปยังหนึ่งในโฟลเดอร์ภายใน (พูด)

ใช้:

mv "`ls -a`" /tony 2>/dev/null

บันทึก:

"`ls -a`" 

หากต้องการย้ายไฟล์ที่มีช่องว่างอยู่

2>/dev/null

สำหรับระงับการเตือน / ข้อผิดพลาดเพราะls -aจะพิมพ์.และ..โฟลเดอร์ด้วยและคุณไม่สามารถย้ายหรือคัดลอกได้ ดังนั้นสำหรับโฟลเดอร์เหล่านั้นมันจะแสดงข้อผิดพลาด (ถ้าเราไม่ใช้ 2> / dev / null) ว่ามันไม่สามารถย้ายมันได้และส่วนที่เหลือจะถูกย้ายอย่างสะดวกสบาย

ที่ดีที่สุดที่จะหลีกเลี่ยงถ้าไม่มีไฟล์ที่ซ่อนอยู่และการใช้งานเพียงแค่ls -als


คุณเคยลองแล้วจะเกิดอะไรขึ้นเมื่อคุณวิ่งmv $(ls -a)? แตะที่ไดเรกทอรีปัจจุบันและไดเรกทอรีด้านล่างเพราะls -aจะแสดงผล..เช่นกัน
Sami Laine

ขอบคุณ @SamiLaine สำหรับคำแนะนำที่ฉันได้ทำการแก้ไข แต่mv ls -a ../จะทำงานได้ตามต้องการใช่มันจะแสดงข้อผิดพลาดเหล่านั้นตามที่ฉันกล่าวถึงข้างต้น แต่นอกเหนือจากนั้นมันจะย้ายโฟลเดอร์ / ไฟล์ที่ต้องการไปยังพาเรนต์ dir
Prabhat Kumar Singh

สิ่งนี้จะไม่ทำงานกับไฟล์ที่มีช่องว่าง
kenorb

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