Hedef dosyalarının mv ile nasıl yazılır?


154

Bir alt dizinde, üst dizine taşımak istediğim bir sürü dosya ve dizim var. Hedef dizinde, üzerine yazılması gereken bazı dosyalar ve dizinler var. Yalnızca hedefte bulunan dosyalara dokunulmadan bırakılmalıdır. Bunu mvyapmaya zorlayabilir miyim ? Bu ( mv * ..) şikayet ediyor

mv: cannot move `xyz' to `../xyz': Directory not empty

Neyi kaçırıyorum?


3
Denedin mv -fmi
Sakisk

Neden mv -fdoğru cevap olmadığını merak ediyorum .
Pedro Lobito

@PedroLobito: Çalışmıyor çünkü? -f yalnızca dosyaların üzerine yazar, ancak hedefte bulunan ve boş olmayan alt dizinleri taşırsanız çalışmaz.
EricSchaefer

Yanıtlar:


117

Sen komutları kullanarak, kaynak hedefe kopyalamak ve sonra silmek zorunda kalacak cp -r * ..izledi rm -rf *.

Kullanarak dizinleri "birleştirebileceğinizi" sanmıyorum mv.


4
Şey, yapmak istemediğim şeydi, çünkü uzun zaman alacak ... Yine de teşekkürler.
EricSchaefer

12
Muhtemelen mvdaha hızlı çünkü aynı dosya sistemindesiniz? Ya cp -ldosyaları gerçekten taşımak yerine, sabit bağlantılar oluşturmak için kullanırsanız ?
mattdm

6
Dosya özniteliklerini (zaman damgası, izinler vb.) Korumak için cp -ayerine kullanmanız gerekir cp -r.
dotancohen

2
Buraya google üzerinden geç gelen kişiler için, aşağıdaki yanıtı @palswim'in verdiği yanıt, verilere yeni sabit bağlantılar oluşturarak ve ardından eski bağlantıları silerek mv'nin davranışını taklit eder. Kısa cevap cp -rl source destination && rm -r source.
William Everett

72

rsyncmuhtemelen burada daha iyi bir seçenek olurdu. Bu kadar basit rsync -a subdir/ ./.

Test ağacım filename: contentsformat:

./file1:root
./file2:root
./dir/file3:dir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

Koşu rsync:

$ rsync -a -v subdir/ ./
sending incremental file list
./
file1
dir/
dir/file3

verir:

./file1:subdir
./file2:root
./dir/file3:subdir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

Ve sonra, öykünmek için mv, muhtemelen kaynak dizini kaldırmak istersiniz:

$ rm -r subdir/

Giving:

./file1:subdir
./file2:parent
./dir/file3:subdir
./dir/file4:dir

Eğer bu yanlışsa, istenen sonucu elde etmek için benzer bir örnek (örneğin, test ağacımı bu cevabın en üstünden kullanarak) verebilir misiniz?


1
rsync kopyaları. Bu soru taşınmakla ilgili.
Gilles

1
@Gilles: Teşekkürler. rm -rTemelde aynı yapmak için sonunda ekledi mv.
Mikel

3
copy ve then-delete, kaynak ve hedef aynı dosya sistemindeyken mv ile aynı değildir. mvatomiktir, inode numaralarını korur (böylece dosya açık kalabilir) ve kopya ve zaman almaz.
Gilles

5
@Gilles: Bunu anlıyorum ama şu anda en önemli cevap cp -r; rm -r. Bence bu anlamda da rsyncbahsetmeye değer.
Mikel

Cp / rm ile zaten yaptım (acil oldu). Gerçekten çok zaman aldı. Gilles senaryo muhtemelen çok daha hızlı olurdu, ama o da çok geç kalmıştı.
EricSchaefer

47

rsync--remove-source-filesparametre ile kopyalandıktan sonra kaynağı silebilir . Bu ne istersen yapmanın uygun bir yolu olmalı.

İtibaren rsync man page:

        --remove-source-files   sender removes synchronized files (non-dir)

Bu gerçekten en iyi cevap. cp -r; rmBoş yer olmadığı için kullanamadım . Bunun yerine rsync --remove-source-filesher iki simge durumuna küçültülmüş disk alanı aynı dosyaların üzerine kopyalamaktan kaçındı.
guaka

20

Bunu cpve ile yapabilirsiniz rm, ancak aktarım yapmaktan kaçınmaya çalıştığınız (muhtemelen) büyük miktarda veriyi kopyalamadan. @mattdm yaptığı açıklamada bunu ima etti ve başka bir sorunun cevabının çeşitli seçenekler hakkında daha kapsamlı bir tartışması oldu.

cp -rlf source destination
rm -r source

Temel olarak, komut -lseçeneği cp, verilerini yeni dosyalara kopyalamak yerine dosyalara zor bağlantılar oluşturur.


1
OP'nin soruyu başlatan görevini zaten tamamladığını biliyorum , ancak umarım bu cevap gelecekte bu sorunu yaşayan herkese yardımcı olabilir.
palswim

Bu gerçekten ihtiyaçları olan cevap. Bunu 60 GB'lık binlerce küçük cyrus e-posta dosyasıyla yaptım ve sadece 21 saniye sürdü.
labradort

Bu aynı zamanda aldığım rota. Sahip cp -al source destinationbilgilerini ve izinlerini korumak için değiştirdim .
piit79

Aslında sizden OP'nin istediği şeyi yapmayı düşünüyorum. -F seçeneğini eklemelisiniz, aksi takdirde dosya mevcut değilse üzerine yazmaz. Bunu onaylayabilir misin yoksa yanlış bir şey mi yapıyorum?
das

@dasKeks: Aslında, cpvarsayılan olarak üzerine yazar. Bu -fseçenek rm, yeniden kopyalamayı denemeden önce dosyayı (giriş ) olduğu gibi kaldırmaya çalışır; bu işlem, işlemi yazmak için açamıyorsa, bazı insanlar bunun yerine bir hata olduğunu görmeyi tercih eder. OP için önemli olup olmadığını bilmiyorum, ama -fyine de cevabımı bayrakla ekledim .
palswim

8

İşte dosyaları alttan altta /path/to/source/rootkarşılık gelen yola taşıyan bir betik /path/to/destination/root.

  • Hem kaynak hem de hedefte bir dizin varsa, içerik tekrar tekrar taşınır ve birleştirilir.
  • Kaynakta bir dosya veya dizin varsa, ancak hedefte bulunmuyorsa, taşınır.
  • Hedefte zaten mevcut olan herhangi bir dosya veya dizin geride kalır. (Özellikle birleştirilmiş dizinler kaynakta geride kalır. Bu düzeltilmesi kolay değildir.)

Dikkat edin, denenmemiş kod.

export dest='/path/to/destination/root'
cd /path/to/source/root
find . -type d \( -exec sh -c '[ -d "$dest/$0" ]' \; -o \
                  -exec sh -c 'mv "$0" "$dest/$0"' {} \; -prune \) \
    -o -exec sh -c '
        if ! [ -e "$dest/$0" ]; then
          mv -f "$0" "$dest/$0"
        fi
' {} \;

İki düzeltmeler: Bir ihtiyaç \;önce -oilk satırında findkomuta ve kaçırmamalıyız !içinde if- bu sadece !değil,\!
llhuii

2

Bu konu yıllardır orada ve google'da hala 1. sırada yer alıyor, bu yüzden başka bir yöntem eklemek istedim. Genelde bunu nasıl yaparım: subdir içeriğini bir tarball'a paketleme, tarball'ı üst dizine taşıma ve sonra varsayılan --overwrite davranışıyla çıkartma. Bu tam olarak aradığınızı yapar. Daha sonra subdir'inizi kaldırabilirsiniz.

cd xyz
tar -cvzpf tmp.tar.gz *
mv tmp.tar.gz ../tmp.tar.gz
cd ..
tar -xvzpf tmp.tar.gz
rm -rf xyz
rm -f tmp.tar.gz

Bu, yalnızca sıkıştırılmış tar dosyası için fazladan alana sahipseniz çalışır. Ve gerçekten geçici tar dosyasını ayıklamadan sonra tutmak ister misiniz?
Anthon,

Tmp dosyasını kaldırmak için düzenlenen kod. Günümüzde, alan çoğu durumda sorun değildir. #terabyteages
Simon Kraus

0

Yeterli depolama alanınız varsa, aşağıdaki şekilde yapabilirsiniz:

mv -bfv directory_1/* directory_2/ # all duplicate source files/directories 
                                   # will have ~ appended to them
find -name "*~" -delete            # will recursively find and delete all files 
                                   # with ~ on the end

Sonunda ~ olan önemli bir dosya olmadığından emin olun, ancak varsa --suffix=whateveryouwantvarsayılanı ekleyebilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.