หากฉันใช้mv
เพื่อย้ายโฟลเดอร์ชื่อ "โฟลเดอร์" ไปยังไดเรกทอรีที่มีอยู่แล้ว "โฟลเดอร์" พวกเขาจะรวมหรือจะถูกแทนที่หรือไม่
หากฉันใช้mv
เพื่อย้ายโฟลเดอร์ชื่อ "โฟลเดอร์" ไปยังไดเรกทอรีที่มีอยู่แล้ว "โฟลเดอร์" พวกเขาจะรวมหรือจะถูกแทนที่หรือไม่
คำตอบ:
mv
ไม่สามารถรวมหรือเขียนทับไดเรกทอรีมันจะล้มเหลวด้วยข้อความ"mv: ไม่สามารถย้าย 'a' เป็น 'b': ไดเรกทอรีไม่ว่าง"แม้ว่าคุณจะใช้--force
ตัวเลือกก็ตาม
คุณสามารถทำงานรอบนี้โดยใช้เครื่องมืออื่น ๆ (เช่นrsync
, find
หรือแม้กระทั่งcp
) แต่คุณต้องพิจารณาอย่างรอบคอบความหมาย:
rsync
สามารถรวมเนื้อหาของไดเรกทอรีหนึ่งเข้ากับอีกไดเรกทอรีหนึ่ง (โดยมีตัวเลือก--remove-source-files
1ตัวเลือกเพื่อลบไฟล์ต้นฉบับเหล่านั้นที่ถ่ายโอนได้อย่างปลอดภัยและด้วยตัวเลือกการสงวนสิทธิ์ / ความเป็นเจ้าของ / เวลาปกติ-a
หากคุณต้องการ) rsync
ของ--link-dest=DIR
ตัวเลือก (การสร้าง hardlinks แทนการคัดลอกเนื้อหาของไฟล์ที่เป็นไปได้) และจะได้รับความหมายคล้ายกับปกติ--remove-source-files
สำหรับสิ่งนี้จะต้องได้รับเส้นทางที่แน่นอนไปยังไดเรกทอรีแหล่งที่มา (หรือเส้นทางสัมพัทธ์จากปลายทางไปยังแหล่งที่มา )
… แต่สิ่งนี้ใช้ในลักษณะที่ไม่ได้ตั้งใจ (ซึ่งอาจหรืออาจไม่ก่อให้เกิดภาวะแทรกซ้อน) ต้องรู้ (หรือกำหนด) พา ธ สัมบูรณ์ไปยังแหล่งที่มา (เพื่อเป็นข้อโต้แย้ง) และปล่อยให้โครงสร้างไดเรกทอรีว่างเปล่าหายไป ต่อ1mv
--link-dest
--link-dest
--link-dest
find
เพื่อสร้างโครงสร้างไดเรกทอรีต้นฉบับใหม่ที่เป้าหมายจากนั้นย้ายแต่ละไฟล์ตามจริงcp
สามารถสร้างฮาร์ดลิงก์ (ใส่ตัวชี้เพิ่มเติมไปยังไฟล์ที่มีอยู่เดิม) ซึ่งสร้างผลลัพธ์คล้ายกับการผสานmv
(และมีประสิทธิภาพ IO มากเนื่องจากมีการสร้างตัวชี้เท่านั้นและไม่มีการคัดลอกข้อมูลจริง) วิธีแก้ปัญหาใดที่เหมาะสม (ขึ้นอยู่กับความเหมาะสม) นั้นขึ้นอยู่กับกรณีการใช้งานเฉพาะของคุณ
เช่นเคยคิดก่อนที่คุณจะดำเนินการคำสั่งเหล่านี้และมีการสำรอง
1: โปรดทราบว่าrsync --remove-source-files
จะไม่ลบไดเรกทอรีใด ๆ ดังนั้นคุณจะต้องทำสิ่งfind -depth -type d -empty -delete
ต่อไปนี้เพื่อกำจัดทรีไดเรกทอรีว่างเปล่า
mv
ใช้งานโดย Debian เท่านั้น - การเน้นที่พยายามเนื่องจาก manpage ไม่ได้พูดถึงพฤติกรรมนี้ ...
--delete
จะลบเฉพาะไฟล์ในไดเรกทอรีปลายทางที่ไม่มีอยู่ในไดเรกทอรีต้นทาง
-H
ฟังก์ชั่นหรือคุณสามารถ hardlink --link-dest
ไฟล์ในรูปแบบต่างๆโดยใช้ ดูหน้าคนก่อนที่จะใช้พวกเขาแม้ว่า
rsync -av /source/ /destination/
(after checking)
rm -rf /source/
--remove-source-files
มีข้อดีของการลบไฟล์ที่ถ่ายโอนสำเร็จเท่านั้นดังนั้นคุณสามารถใช้find
เพื่อลบไดเรกทอรีที่ว่างเปล่าและจะถูกทิ้งไว้กับทุกสิ่งที่ไม่ได้ถ่ายโอนโดยไม่ต้องตรวจสอบrsync
เอาต์พุต
คุณสามารถใช้-l
ตัวเลือกของคำสั่งcpซึ่งสร้างการเชื่อมโยงอย่างหนักของไฟล์ในระบบไฟล์เดียวกันแทนการคัดลอกข้อมูลแบบเต็ม คำสั่งต่อไปนี้คัดลอกโฟลเดอร์source/folder
ไปยังโฟลเดอร์หลัก ( destination
) ซึ่งมีไดเรกทอรีที่มีชื่อfolder
อยู่แล้ว
cp -rl source/folder destination
rm -r source/folder
คุณอาจต้องการใช้-P
( --no-dereference
- อย่ายกเลิกการเชื่อมโยงสัญลักษณ์อ้างอิง) หรือ-a
( --archive
- สงวนข้อมูลเมตาทั้งหมดรวมถึง-P
ตัวเลือก) ขึ้นอยู่กับความต้องการของคุณ
cp
แทนที่จะเป็นrsync
เพราะทุกระบบมีcp
และทุกคนมีความคุ้นเคยกับมัน
cp
mv
-n
mv /fs1/file /fs2/
(ข้ามระบบไฟล์) จะทำการคัดลอกและลบ
mv
จะใช้งานได้ (หาก dir เป้าหมายยังไม่มีอยู่) แม้ว่าจะไม่ "มีประสิทธิภาพ" หรือสิ่งที่คุณเรียกมันcp -rl
จะล้มเหลว
ฉันขอแนะนำสี่ขั้นตอนเหล่านี้:
cd ${SOURCE};
find . -type d -exec mkdir -p ${DEST}/\{} \;
find . -type f -exec mv \{} ${DEST}/\{} \;
find . -type d -empty -delete
หรือดีกว่ายังนี่เป็นสคริปต์ที่ใช้ความหมายคล้ายกับmv
:
#!/bin/bash
DEST="${@:${#@}}"
ABS_DEST="$(cd "$(dirname "$DEST")"; pwd)/$(basename "$DEST")"
for SRC in ${@:1:$((${#@} -1))}; do (
cd "$SRC";
find . -type d -exec mkdir -p "${ABS_DEST}"/\{} \;
find . -type f -exec mv \{} "${ABS_DEST}"/\{} \;
find . -type d -empty -delete
) done
rsync -u
(อัปเดตเฉพาะในกรณีที่ใหม่กว่า) mv
(ในบางรุ่นอย่างน้อย) สามารถใช้-u
ตัวเลือก อย่างไรก็ตามในกรณีดังกล่าวคุณอาจต้องการลบไดเรกทอรีต้นทางที่ไม่ว่างเปล่ารวมถึงไดเรกทอรีว่างเปล่าเพื่อให้ครอบคลุมกรณีที่ไฟล์ในแผนผังต้นไม้ไม่ใหม่ @schuess: ดูเหมือนว่าอาจมีอาร์กิวเมนต์ SOURCE หลายรายการหากคุณต้องการ
นี่คือวิธีที่จะรวมไดเรกทอรี มันเร็วกว่า rsync เพียงแค่เปลี่ยนชื่อไฟล์แทนการคัดลอกแล้วลบทิ้ง
cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'
dest
นั้นเป็นไดเรกทอรีที่มีชื่อเดียวกันกับในsource
แล้ว และไฟล์จะถูกย้ายไปยังที่อยู่ในdest
source
คำสั่งไม่ทำอะไรเลยมากกว่าmv source/* source/dest/.
วิธีหนึ่งที่จะทำให้สิ่งนี้สำเร็จคือใช้:
mv folder/* directory/folder/
rmdir folder
ตราบใดที่ไม่มีไฟล์สองไฟล์ที่มีชื่อเหมือนกันfolder
และdirectory/folder
คุณจะได้ผลลัพธ์เช่นการผสาน
rm folder
ทำงานอย่างไร
rm folder -fR
ใช้ได้กับฉันเสมอ
สำหรับสำเนาที่บริสุทธิ์ที่สุดฉันใช้วิธีคัดลอก tar (-) B blockread
ตัวอย่างจากภายในพา ธ ต้นทาง ('cd' ที่นั่นหากจำเป็น):
tar cBf - <sourcefolder> | (cd /your/target/folder ; tar xBf -)
สิ่งนี้จะสร้างสำเนาต้นไม้ต้นกำเนิดที่แน่นอนโดยที่เจ้าของและสิทธิ์อนุญาตยังคงเหมือนเดิม และหากมีโฟลเดอร์เป้าหมายข้อมูลจะถูกรวมเข้าด้วยกัน เฉพาะไฟล์ที่มีอยู่แล้วเท่านั้นที่จะถูกเขียนทับ
ตัวอย่าง:
$ cd /data1/home
$ tar cBf - jdoe | (cd /data2/home ; tar xBf -)
เมื่อการคัดลอกเสร็จสมบูรณ์คุณสามารถลบแหล่งที่มา ( rm -rf <source>
) แน่นอนว่านี่ไม่ใช่การย้ายที่แน่นอน: ข้อมูลจะถูกคัดลอกจนกว่าคุณจะลบแหล่งที่มา
ในฐานะที่เป็นตัวเลือกที่คุณสามารถ verbose (แสดงบนหน้าจอไฟล์ที่ถูกคัดลอก) ด้วย -v: tar cBvf -
c
: สร้างB
: read full block (สำหรับไปป์ read)v
: verbosef
: ไฟล์ที่จะเขียนx
: สารสกัด-
: stdout / stdinsourcefolder
สามารถเป็นได้*
(สำหรับทุกอย่างในโฟลเดอร์ปัจจุบัน)
f -
tar โดยปกติไม่จำเป็น - ค่าดีฟอลต์คืออ่านจาก stdin / write to stdout
นี่คือสคริปต์ที่เหมาะกับฉัน ฉันชอบ mv มากกว่า rsync ดังนั้นฉันจึงใช้โซลูชั่นของ Jewel และ Jonathan Mayer
#!/bin/bash
# usage source1 .. sourceN dest
length=$(($#-1))
sources=${@:1:$length}
DEST=$(readlink -f ${!#})
for SRC in $sources; do
pushd $SRC;
find . -type d -exec mkdir -p ${DEST}/{} \;
find . -type f -exec mv {} ${DEST}/{} \;
find . -type d -empty -delete
popd
done
ไม่ใช่ความคิดที่ดีที่จะใช้คำสั่งเช่น cp หรือ rsync สำหรับไฟล์ขนาดใหญ่มันจะใช้เวลานาน mv เร็วกว่ามากเพราะมันอัพเดตเฉพาะ inodes โดยไม่ทำการคัดลอกไฟล์ทางกายภาพ ตัวเลือกที่ดีกว่าคือการใช้ตัวจัดการไฟล์ของระบบปฏิบัติการของคุณ สำหรับ Opensuse จะมีโปรแกรมจัดการไฟล์ชื่อ Konquerer มันสามารถย้ายไฟล์ได้โดยไม่ต้องคัดลอกไฟล์จริง มันมีฟังก์ชั่น "ตัดและวาง" เหมือนใน Windows เพียงเลือกไดเรกทอรีย่อยทั้งหมดในไดเรกทอรี A. คลิกขวาและ "ย้ายเข้าไปใน" ไดเรกทอรี B ซึ่งอาจมีไดเรกทอรีย่อยที่มีชื่อเดียวกัน มันจะรวมพวกเขา นอกจากนี้ยังมีตัวเลือกว่าคุณต้องการเขียนทับหรือเปลี่ยนชื่อไฟล์ด้วยชื่อเดียวกัน
mv
มีการใช้งาน
Python solution
เนื่องจากฉันไม่สามารถหาวิธีแก้ไขปัญหาที่มีอยู่แล้วที่น่าพอใจฉันตัดสินใจที่จะสร้างสคริปต์ Python อย่างรวดเร็วเพื่อให้บรรลุ
โดยเฉพาะอย่างยิ่งวิธีการนี้มีประสิทธิภาพเพราะจะเดินทรีไฟล์ต้นฉบับเพียงครั้งเดียวเท่านั้น
นอกจากนี้ยังช่วยให้คุณปรับแต่งสิ่งต่างๆอย่างรวดเร็วเช่นเขียนทับไฟล์ที่คุณต้องการ
การใช้งาน:
move-merge-dirs src/ dest/
จะย้ายเนื้อหาทั้งหมดของsrc/*
ไปยังdest/
และsrc/
จะหายไป
ย้ายผสาน-dirs
#!/usr/bin/env python3
import argparse
import os
def move_merge_dirs(source_root, dest_root):
for path, dirs, files in os.walk(source_root, topdown=False):
dest_dir = os.path.join(
dest_root,
os.path.relpath(path, source_root)
)
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
for filename in files:
os.rename(
os.path.join(path, filename),
os.path.join(dest_dir, filename)
)
for dirname in dirs:
os.rmdir(os.path.join(path, dirname))
os.rmdir(source_root)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Move merge src/* into dest. Overwrite existing files.'
)
parser.add_argument('src_dir')
parser.add_argument('dest_dir')
args = parser.parse_args()
move_merge_dirs(args.src_dir, args.dest_dir)
GitHub ต้นน้ำ
ดูเพิ่มเติมที่: https://stackoverflow.com/questions/22588225/how-do-you-merge-two-directories-or-move-with-replace-from-the-windows-command
นี่คือคำสั่งสำหรับการย้ายไฟล์และโฟลเดอร์ไปยังปลายทางอื่น:
$ mv /source/path/folder /target/destination/
โปรดจำไว้ว่า : mv
คำสั่งจะไม่ทำงานหากโฟลเดอร์จะถูกรวมเข้าด้วยกัน (เช่นโฟลเดอร์อื่นที่มีชื่อเดียวกันอยู่แล้วในปลายทาง) และปลายทางไม่ว่างเปล่า
mv: ไม่สามารถย้าย '/ source / path / folder' เป็น '/ target / destination / folder': ไดเรกทอรีไม่ว่างเปล่า
หากโฟลเดอร์ปลายทางว่างเปล่าคำสั่งด้านบนจะทำงานได้ดี
ดังนั้นในการรวมทั้งสองโฟลเดอร์เข้าด้วยกัน
ไม่ว่าจะในกรณีใดให้ทำใน 2 คำสั่ง:
$ cp -rf /source/path/folder /target/destination/
$ rm -rf /source/path/folder
หรือรวมทั้งสองเป็นคำสั่งแบบครั้งเดียว:
$ cp -rf /source/path/folder /target/destination/ && rm -rf /source/path/folder
mv = move
cp = copy
rm = remove-rสำหรับไดเรกทอรี (โฟลเดอร์)
-f การบังคับให้ทำงาน
mv
ครั้ง คำตอบนี้จะดีขึ้นด้วยความจริงที่กว้างขึ้น Linux, BSD และ Unix "ของจริง" หรืออ้างอิงจาก POSIX หรือ SUS