Yanıtlar:
mv
dizinleri birleştiremez veya üzerine yazamazsa , --force
seçeneği kullanırken bile "mv: 'a' '' b ': Dizin boş değil' iletisini alamazsınız .
Bunun için başka araçlar (örneğin rsync
, find
hatta cp
) bile kullanabilirsiniz , ancak sonuçları dikkatlice düşünmelisiniz:
rsync
Bir dizinin içeriğini bir başkasına birleştirebilir (ideal olarak yalnızca başarılı bir şekilde aktarılan kaynak dosyaları güvenle silme seçeneği ile --remove-source-files
1 seçeneğinde ve isterseniz normal izin / sahiplik / zaman koruma seçeneğiyle -a
) rsync
'ın --link-dest=DIR
ve (yerine mümkün kopyalama dosya içeriklerin sabit bağları oluşturmak için) seçeneğini --remove-source-files
düzenli bir semantik çok benzer olsun mv
. --link-dest
mutlak bir yol verilmesi gereken kaynak dizin (veya bir göreli yol hedef için kaynak ). --link-dest
istenmeyen bir şekilde (komplikasyonlara neden olabilir veya etmeyebilir) kullanıyor, kaynağa giden mutlak yolu (argüman olarak --link-dest
) bilmeyi (veya belirlemeyi) gerektiriyor ve tekrar gibi boş bir dizin yapısını bırakıyor 1 başına .find
Kaynak dizin yapısını hedefteki sırayla yeniden oluşturmak için kullanabilirsiniz , sonra asıl dosyaları ayrı ayrı hareket ettirin cp
Sert bağlantılar oluşturabilirsiniz kaynaşmasında çok benzer bir sonuç yaratır, (basitçe aynı varolan dosyaya ek işaretçileri koymak) mv
(ve yalnızca işaretçiler oluşturulan ve hiçbir gerçek veri kopyalanacak vardır çünkü çok IO-verimli) Bu geçici çözümlerden hangisinin (varsa) uygun olduğu özel kullanım durumunuza büyük ölçüde bağlı olacaktır.
Her zamanki gibi, bu komutlardan herhangi birini yerine getirmeden önce düşünün ve yedekleriniz olsun.
1: rsync --remove-source-files
Dizinleri silmeyeceğinize dikkat edin, bu nedenle find -depth -type d -empty -delete
boş kaynak dizin ağacından kurtulmak için daha sonra yapmanız gerekenleri yapın .
mv
Debian tarafından kullanılan uygulama - vurgu olmak çalıştı manpage bu davranışı söz etmez çünkü ...
--delete
Yalnızca kaynak dizinde bulunmayan hedef dizindeki dosyaları siler .
-H
işlevle yalnızca sabit bağlantıları koruyabilir veya hedef kullanarak dosyaları sabit bağlama yapabilirsiniz --link-dest
. Yine de kullanmadan önce man sayfasına bakınız.
rsync -av /source/ /destination/
(after checking)
rm -rf /source/
--remove-source-files
yalnızca başarılı bir şekilde aktarılan dosyaları kaldırma avantajına sahiptir, bu nedenle find
boş dizinleri kaldırmak için kullanabilirsiniz ve rsync
s çıkışını kontrol etmek zorunda kalmadan aktarılmayan her şeyle birlikte kalacaksınız .
Tam veri kopyaları yerine aynı dosya sisteminde sabit dosya bağlantıları oluşturan cp komutunun -l
seçeneğini kullanabilirsiniz . Aşağıdaki komut, klasörü zaten adı olan bir dizin içeren bir üst klasöre ( ) kopyalar .source/folder
destination
folder
cp -rl source/folder destination
rm -r source/folder
Ayrıca kullanmak isteyebilirsiniz -P
( --no-dereference
- de-referans sembolik linkler yoktur) veya -a
( --archive
- tüm meta korumak, aynı zamanda içerir -P
seçeneği), ihtiyaçlarınıza bağlı.
cp
olduğundan rsync
beri cp
.
cp
İşlem süresi ile birleştirme yeteneği olsun mv
.
-n
mv /fs1/file /fs2/
(dosya sistemlerinde) bir kopya ve ardından bir silme gerçekleştirir.
mv
“verimli bir şekilde” olmasın veya ne diyorsanız çalışsanız bile (hedef direktör henüz mevcut değilse) cp -rl
çalışacaktır.
Bu dört adımı tavsiye ederim:
cd ${SOURCE};
find . -type d -exec mkdir -p ${DEST}/\{} \;
find . -type f -exec mv \{} ${DEST}/\{} \;
find . -type d -empty -delete
veya daha iyisi, işte benzer bir anlambilim uygulayan bir betik 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
(yalnızca yeniyse güncelle), mv
(en azından bazı sürümlerde) de bu -u
seçeneği kullanabilir. Ancak bu durumda, kaynak ağacındaki dosyaların daha yeni olmadığı durumlarda, boş olmayan kaynak dizinleri ve boş olanları silmek isteyebilirsiniz. @schuess: Gerekirse birden fazla SOURCE argümanı olabilir gibi görünüyor.
İşte dizinleri birleştirecek bir yol. Dosyaları kopyalamak ve silmek yerine yalnızca yeniden adlandırdığından, rsync'den çok daha hızlıdır.
cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'
dest
Zaten içinde ile aynı ada sahip bir dizinse, komut başarısız olur source
. Ve dosyalar taşınır dest
içinde olan source
. Komut hiçbir şey yapmazmv source/* source/dest/.
Bunu başarmanın bir yolu kullanmak olacaktır:
mv folder/* directory/folder/
rmdir folder
Sürece İki dosya aynı ada sahip olarak folder
ve directory/folder
, sen birleştirme yani aynı sonucu elde edecektir.
rm folder
çalışıyor?
rm folder -fR
her zaman benim için çalışır
En saf kopyalar için, tar (-) B blockread copy yöntemini kullanıyorum.
örneğin, kaynak yolunun içinden (gerekirse orada 'cd' var):
tar cBf - <sourcefolder> | (cd /your/target/folder ; tar xBf -)
bu kaynak ağacın tam bir kopyasını yaratır, sahibiyle ve izinleri bozulmadan. Hedef klasör varsa, veriler birleştirilir. Sadece önceden var olan dosyaların üzerine yazılacaktır.
Örnek:
$ cd /data1/home
$ tar cBf - jdoe | (cd /data2/home ; tar xBf -)
Kopyalama işlemi başarılı olduğunda kaynağı ( rm -rf <source>
) kaldırabilirsiniz . Tabii ki bu kesin bir hamle değil: Siz kaynağı kaldırana kadar veriler kopyalanacaktır.
Seçenek olarak, -v ile ayrıntılı olabilir (ekranda kopyalanan dosyayı görüntüleyin). tar cBvf -
c
: yaratmak, yapmak, tasarlamak, üretmekB
: tam bloğu oku (boru okuması için)v
: ayrıntılıf
: yazmak için dosyax
: Ayıkla-
: stdout / stdinsourcefolder
olabilir *
(geçerli klasördeki herhangi bir şey için)
f -
genellikle gereksizdir - varsayılan, stdin / write'dan stdout'a okumaktır.
İşte benim için çalışan bir senaryo. Rsync yerine mv'yi tercih ediyorum, bu yüzden Jewel ve Jonathan Mayer'in çözümlerini kullanıyorum.
#!/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 veya rsync gibi komutları kullanmak iyi bir fikir değildir. Büyük dosyalar için uzun zaman alacaktır. mv dosyaları fiziksel olarak kopyalamaksızın sadece inode'ları güncellediğinden çok daha hızlıdır. İşletim sisteminizin dosya yöneticisini kullanmak daha iyi bir seçenek olabilir. Opensuse için Konquerer adında bir dosya yöneticisi var. Dosyaları gerçekten kopyalamaksızın taşıyabilir. Windows'taki gibi "kes ve yapıştır" işlevine sahiptir. A dizinindeki tüm alt dizinleri seçmeniz yeterlidir, sağ tıklayın ve aynı isimlere sahip alt dizinler içerebilen B dizinine "hareket ettirin". Onları birleştirecek. Aynı addaki dosyaların üzerine yazmak veya yeniden adlandırmak isteyip istemediğinizi de seçebilirsiniz.
mv
kullanıldığında ne olacağını soruyor .
Python çözümü
Önceden tatmin edici bir çözüm bulamadığım için hızlı bir Python senaryosu hazırlamaya karar verdim.
Özellikle, bu yöntem etkilidir çünkü kaynak dosya ağacını sadece bir kere yukarı doğru yürür.
Ayrıca, dosya üzerine yazma gibi şeyleri istediğiniz gibi hızla değiştirebilmenizi sağlar.
Kullanımı:
move-merge-dirs src/ dest/
tüm içeriği src/*
içine taşıyacak dest/
ve src/
kaybolacak.
move-birleştirme-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)
Ayrıca bakınız: https://stackoverflow.com/questions/22588225/how-do-you-merge-two-directories-or-move-with-replace-from-the-windows-command
Bu, dosyaları ve klasörleri başka bir hedefe taşımak için kullanılan komuttur:
$ mv /source/path/folder /target/destination/
Unutmayın : mv
Klasör b̲e̲i̲n̲g m̲e̲r̲ge̲d̲ (yani, aynı adda başka bir klasör hedefte zaten var ise) ve d̲e̲s̲t̲i̲n̲a̲t̲i̲o̲n̲ o̲n̲e̲ i̲s̲ n̲o̲t̲ e̲m̲p̲p̲y̲t .
mv: '/ source / path / folder' '/ target / destination / folder' konumuna getirilemiyor: Dizin boş değil
Hedef klasör boşsa, yukarıdaki komut iyi çalışacaktır.
Yani, her iki klasörü de birleştirmek için,
iki komutla da yapın:
$ cp -rf /source/path/folder /target/destination/
$ rm -rf /source/path/folder
Veya her ikisini de tek seferlik bir komut olarak birleştirin:
$ cp -rf /source/path/folder /target/destination/ && rm -rf /source/path/folder
mv = hareket
cp = kopya
rm = kaldır-r dizini (klasörü)
-f zorla yürütme
mv
. Bu cevap daha geniş bir gerçeklikte daha iyi olurdu. Linux, BSD ve "real" Unix veya POSIX veya SUS'tan referans.