Jawaban:
mv
tidak dapat menggabungkan atau menimpa direktori, itu akan gagal dengan pesan "mv: tidak dapat memindahkan 'a' ke 'b': Direktori tidak kosong" , bahkan ketika Anda menggunakan --force
opsi.
Anda bisa menyiasatinya dengan menggunakan alat-alat lain (seperti rsync
, find
, atau bahkan cp
), tetapi Anda perlu hati-hati mempertimbangkan implikasi:
rsync
dapat menggabungkan konten dari satu direktori ke direktori lain (idealnya dengan opsi --remove-source-files
1 untuk menghapus dengan aman hanya file-file sumber yang berhasil ditransfer, dan dengan opsi pelestarian izin / kepemilikan / waktu yang biasa -a
jika Anda inginkan) rsync
's --link-dest=DIR
pilihan (untuk membuat hardlinks bukan menyalin isi file, jika mungkin) dan --remove-source-files
untuk mendapatkan semantik sangat mirip dengan biasa mv
. --link-dest
perlu diberikan jalur absolut ke direktori sumber (atau jalur relatif dari tujuan ke sumber ). --link-dest
cara yang tidak disengaja (yang mungkin atau mungkin tidak menyebabkan komplikasi), membutuhkan mengetahui (atau menentukan) jalur absolut ke sumber (sebagai argumen untuk --link-dest
), dan sekali lagi meninggalkan struktur direktori kosong untuk dibersihkan sebagai per 1 .find
untuk secara berurutan membuat ulang struktur direktori sumber pada target, kemudian secara individual memindahkan file yang sebenarnya cp
dapat membuat tautan keras (sederhananya, pointer tambahan ke file yang ada sama), yang menciptakan hasil yang sangat mirip dengan penggabungan mv
(dan sangat IO-efisien karena hanya pointer dibuat dan tidak ada data aktual yang harus disalin) Manakah dari solusi ini (jika ada) yang sesuai akan sangat tergantung pada kasus penggunaan khusus Anda.
Seperti biasa, pikirkan sebelum Anda menjalankan salah satu dari perintah ini, dan miliki cadangan.
1: Perhatikan bahwa rsync --remove-source-files
tidak akan menghapus direktori apa pun, jadi Anda harus melakukan sesuatu seperti find -depth -type d -empty -delete
sesudahnya untuk menyingkirkan pohon direktori sumber kosong.
mv
implementasi yang digunakan oleh Debian - penekanan sedang dicoba , karena halaman manual tidak menyebutkan perilaku ini ...
--delete
hanya menghapus file di direktori tujuan yang tidak ada di direktori sumber.
-H
fungsi atau Anda dapat menghubungkan tautan di file dengan tujuan --link-dest
. Lihat halaman manual sebelum menggunakannya.
rsync -av /source/ /destination/
(after checking)
rm -rf /source/
--remove-source-files
memiliki keuntungan hanya dengan menghapus file yang berhasil ditransfer, sehingga Anda dapat menggunakan find
untuk menghapus direktori kosong dan akan dibiarkan dengan semua yang tidak ditransfer tanpa harus memeriksa rsync
output.
Anda dapat menggunakan -l
opsi perintah cp , yang menciptakan tautan keras file pada sistem file yang sama dan bukan salinan data lengkap. Perintah berikut menyalin folder source/folder
ke folder induk ( destination
) yang sudah berisi direktori dengan nama folder
.
cp -rl source/folder destination
rm -r source/folder
Anda mungkin juga ingin menggunakan -P
( --no-dereference
- jangan menghapus tautan simbolik referensi) atau -a
( --archive
- mempertahankan semua metadata, juga menyertakan -P
opsi), tergantung pada kebutuhan Anda.
cp
bukannya rsync
karena setiap sistem memiliki cp
dan semua orang memiliki keakraban dengannya.
cp
dengan waktu operasi mv
.
-n
mv /fs1/file /fs2/
(lintas filesystem) akan melakukan salinan dan kemudian menghapus.
mv
akan bekerja (asalkan target direktori belum ada) bahkan jika tidak "efisien" atau apa pun namanya, cp -rl
akan gagal.
Saya akan merekomendasikan empat langkah ini:
cd ${SOURCE};
find . -type d -exec mkdir -p ${DEST}/\{} \;
find . -type f -exec mv \{} ${DEST}/\{} \;
find . -type d -empty -delete
atau lebih baik lagi, inilah skrip yang mengimplementasikan semantik yang mirip dengan 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
(hanya perbarui jika lebih baru), mv
(dalam beberapa versi setidaknya) juga dapat mengambil -u
opsi. Namun dalam hal ini Anda mungkin ingin menghapus direktori sumber yang tidak kosong dan juga direktori yang kosong, untuk menutup kasus-kasus di mana file dalam pohon sumber tidak lebih baru. @ schuess: Sepertinya ada beberapa argumen SUMBER, jika Anda membutuhkannya.
Berikut adalah cara yang akan menggabungkan direktori. Ini jauh lebih cepat daripada rsync karena hanya mengganti nama file daripada menyalinnya dan kemudian menghapusnya.
cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'
dest
sudah direktori dengan nama yang sama seperti pada source
. Dan file akan dipindahkan ke dest
, yang ada di source
. Perintah itu tidak lebih darimv source/* source/dest/.
Salah satu cara untuk mencapai ini adalah dengan menggunakan:
mv folder/* directory/folder/
rmdir folder
Selama tidak ada dua file memiliki nama yang sama folder
dan directory/folder
, Anda akan mencapai hasil yang sama yaitu penggabungan.
rm folder
kerjanya?
rm folder -fR
selalu bekerja untukku
Untuk salinan yang paling murni, saya menggunakan metode salin blockread tar (-) B.
contoh, dari dalam jalur sumber ('cd' di sana jika perlu):
tar cBf - <sourcefolder> | (cd /your/target/folder ; tar xBf -)
ini membuat salinan persis pohon sumber, DENGAN pemilik dan izin utuh. Dan jika folder target ada, data akan digabungkan. Hanya file yang sudah ada yang akan ditimpa.
Contoh:
$ cd /data1/home
$ tar cBf - jdoe | (cd /data2/home ; tar xBf -)
Ketika tindakan salin berhasil, Anda dapat menghapus sumber ( rm -rf <source>
). Tentu saja ini bukan langkah yang tepat: data akan disalin, sampai Anda menghapus sumbernya.
Sebagai opsi, Anda dapat menggunakan verbose (menampilkan pada layar file yang sedang disalin), dengan -v: tar cBvf -
c
: buatB
: baca blok penuh (untuk pipa baca)v
: verbosef
: file untuk ditulisx
: ekstrak-
: stdout / stdinsourcefolder
bisa juga *
(untuk apa pun di folder saat ini)
f -
tar biasanya tidak diperlukan - standarnya adalah membaca dari stdin / write ke stdout.
Berikut ini skrip yang berfungsi untuk saya. Saya lebih suka mv daripada rsync, jadi saya menggunakan solusi Jewel dan 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
Bukan ide yang baik untuk menggunakan perintah seperti cp atau rsync. Untuk file besar, itu akan memakan waktu lama. mv jauh lebih cepat karena hanya memperbarui inode tanpa menyalin file secara fisik. Opsi yang lebih baik adalah menggunakan pengelola file sistem operasi Anda. Untuk Opensuse, ada pengelola file bernama Konquerer. Itu dapat memindahkan file tanpa benar-benar menyalinnya. Ini memiliki fungsi "memotong dan menempel" seperti di Windows. Cukup pilih semua sub-direktori di direktori A. Klik kanan dan "pindah ke" direktori B yang mungkin berisi sub-direktori dengan nama yang sama. Itu akan menggabungkan mereka. Ada juga opsi apakah Anda ingin menimpa atau mengganti nama file dengan nama yang sama.
mv
digunakan.
Solusi python
Karena saya tidak dapat menemukan solusi yang sudah ada yang memuaskan, saya memutuskan untuk membuat skrip Python cepat untuk mencapainya.
Secara khusus, metode ini efisien karena hanya berjalan pohon sumber file sekali dari bawah ke atas.
Ini juga akan memungkinkan Anda untuk dengan cepat men-tweak hal-hal seperti penanganan file overwrite sesuai keinginan Anda.
Pemakaian:
move-merge-dirs src/ dest/
akan memindahkan semua konten src/*
ke dest/
dan src/
akan menghilang.
move-merge-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)
Ini adalah perintah untuk memindahkan file & folder ke tujuan lain:
$ mv /source/path/folder /target/destination/
Ingat : mv
perintah tidak akan berfungsi jika folder tersebut adalah b̲e̲i̲n̲g m̲e̲r̲ge̲d̲ (yaitu folder lain dengan nama yang sama sudah ada di tujuan) dan d̲e̲s̲t̲i̲n̲a̲t̲i̲o̲n̲ o̲n̲e̲ i̲s̲ n̲o̲t̲ e̲m̲pt̲y .
mv: tidak dapat memindahkan '/ source / path / folder' ke '/ target / destination / folder': Direktori tidak kosong
Jika folder tujuan kosong, perintah di atas akan berfungsi dengan baik.
Jadi, untuk menggabungkan kedua folder dalam hal apa pun,
lakukan dalam 2 perintah:
$ cp -rf /source/path/folder /target/destination/
$ rm -rf /source/path/folder
Atau gabungkan keduanya sebagai perintah satu kali:
$ cp -rf /source/path/folder /target/destination/ && rm -rf /source/path/folder
mv = pindah
cp = salin
rm = hapus-r untuk direktori (folder)
-f eksekusi paksa
mv
. Jawaban ini akan lebih baik dengan kebenaran yang lebih luas. Linux, BSD dan Unix "nyata", atau referensi dari POSIX atau SUS.