Bash: Klasör yapısını koruyarak adlandırılmış dosyaları yinelemeli olarak kopyalayın


103

Umuyordum:

cp -R src/prog.js images/icon.jpg /tmp/package

hedef dizinde simetrik bir yapı oluşturur:

/tmp
|
+-- package
    |
    +-- src
    |   |
    |   +-- prog.js
    |
    +-- images
        |
        +-- icon.jpg

bunun yerine, her iki dosya da / tmp / package içine kopyalanır. Düz bir kopya. (Bu OSX üzerindedir).

Joker karakterle (ör. Src / *. Js) belirtilen dosyalar dahil olmak üzere tüm dosyaları hedef dizindeki haklı yerlerine kopyalamak için kullanabileceğim basit bir bash işlevi var mı? Biraz "her dosya için çalıştır mkdir -p $(dirname "$file"); cp "$file" $(dirname "$file")" gibi, ama belki de tek bir komut.

Bu, bunun mümkün olmadığını gösteren alakalı bir konu. Yazarın çözümü benim için pek kullanışlı değil, çünkü sadece bir dosya listesi, joker karakter olsun ya da olmasın ve hepsinin hedef dizine kopyalanmasını istiyorum. IIRC MS-DOS xcopy bunu yapar, ancak cp için bir eşdeğeri yok gibi görünüyor.

Yanıtlar:


154

--Parents seçeneğini kullanmayı denediniz mi? OS X bunu destekliyor mu bilmiyorum ama bu Linux'ta çalışıyor.

cp --parents src/prog.js images/icon.jpg /tmp/package

Bu OS X'te işe yaramazsa, deneyin

rsync -R src/prog.js images/icon.jpg /tmp/package

aif önerdiği gibi.


4
Teşekkürler. Mac'te "cp --parents" kullanılamaz, ancak diğer unixenlerin bayrağını bilmek güzel. rsync -R, bu sorun için en basit taşınabilir çözümdür.
mahemoff

1
Bunu zarafeti / hatırlanabilirliği için kabul ettim, ancak bunun tüm dizinleri (en azından OSX'te) kopyalamadığını keşfettim, oysa aşağıdaki tar.
mahemoff

cp --parentsOSX'te (BSD cp) geçersiz bir seçenektir, ancak gcp(GNU cp) iyi çalışıyor. Henüz sisteminizde yoksa kullanın brew install coreutils. U, g-ön ekli birçok yardımcı programa sahip olacaktır.
kyb

@mahemoff cp -R --parentsve rsync -rRhem dosyaları hem de dizinleri nispeten kopyalar.
Vortico

22

Tek yön:

tar cf - <files> | (cd /dest; tar xf -)

Oh, bunu cevabımdan çok daha çok seviyorum.
EMPraptor

4
Ayrıca -Cchdir'i sizin için yapma seçeneğini tar cf - _files_ | tar -C /dest xf -veya bunun gibi bir şeyi de kullanabilirsiniz.
D.Shawley

teşekkürler, bu kısa, ancak basitlik için rsync'i tercih ediyorum.
mahemoff

1
Harika! Bunu nasıl bir kabuk komutuna çevireceğini bilen var mı? N giriş kabul etmelidir, ilk N-1 kopyalanacak dosyalardır ve sonuncusu hedef klasördür.
arod

@arod $ {! #} son parametredir ve bunu önceki bağımsız değişkenleri almak için kullanın stackoverflow.com/questions/1215538/… . Komutu yazarsanız, lütfen buradaki öze bağlantı verin.
mahemoff

18

Alternatif olarak, eski kafalıysanız, cpio'yu kullanın:

cd /source;
find . -print | cpio -pvdmB /target

Açıkça, dosya listesini kalbinizin içeriğine göre filtreleyebilirsiniz.

'-P' seçeneği 'geçiş' modu içindir (giriş için '-i' veya çıkış için '-o' ile olduğu gibi). '-V' ayrıntılıdır (dosyaları işlendikçe listeleyin). '-M', değişiklik sürelerini korur. '-B', 'büyük blokların' kullanılması anlamına gelir (burada büyük bloklar 512 bayt yerine 5120 bayttır); bu günlerde hiçbir etkisi olmayabilir.


1
Özel karakterlerle bozulmaması için seçenek -print0kombinasyonu ile kullanmak daha iyidir --null:find . -print0 | cpio -pvdmB --null /target
haridsv

Eski okul deyin, taşınabilir deyin, her neyse, ama kesinlikle cpiobu göreve güveniyorum . -print0Ve -nullseçeneklerinin kullanılması gerektiğini kabul ediyorum , aksi takdirde bir noktada birisi size 'özel karakterler' (büyük olasılıkla boşluklar) içeren klasörler verir ve bir şey olur. Kişisel deneyimlerimden bahsettiğimden değil, ancak bir grup dosyayı yedeklemeyi deneyebilir ve dosya adlarındaki boşluklar nedeniyle bunların yalnızca yarısı yedeklenebilir. (Tamam, kişisel deneyimlerime dayanarak söylüyorum.)
bballdave025

@ bballdave025: Yalnızca cpiodosya adları yeni satırlar içeriyorsa gösterilen sorunlarla karşılaşırsınız - o zaman normalde bir dosya adındaki her satırsonu için bulunmayan iki (veya daha fazla) dosya adı hakkında bir hata mesajı alırsınız. (Bazen daha az mesaj alabilirsiniz - ancak bu, test senaryosunu oluştururken büyük özen gerektirir.). Kullandığımda cpiohiçbir --nullseçenek yoktu ; çift ​​çizgi seçenekleri SVR4 seçenek gösterimlerinin bir parçası değildi ve kavramı ikisinde -print0de mevcut değildi find. Ama bu çok uzun zaman önceydi (örneğin 90'ların ortası, Linux hakimiyet kurmadan önce).
Jonathan Leffler

Ayrıntılar için teşekkürler, @Jonathan_Leffler. Burada bir şeyler öğrenmeyi seviyorum. Şimdi, yaptığım yinelemeli kopyalama hatasını hatırlamaya çalışıyorum, bu bana boşluklarla ilgili sorunlara neden oldu - bu hatayı yapabileceğim birçok yol var,
bballdave025

@ bballdave025— Karışımda bir olasılık kullanılıyor xargs- beyaz boşlukta bölünüyor - boşluklar, sekmeler, satırsonları. OTOH, bunu nasıl ve neden yaptığından emin değilim. cpioÇıktı kipindeki GNU kılavuzu, satır başına bir dosya adı hakkında açıktır. SVR4 kullanım kılavuzu (1990 basımı) belirsizdir: cpio -o(kopyalama modu) bir yol adı listesi elde etmek için standart girişi okur ve bu dosyaları yol adı ve durum bilgileriyle birlikte standart çıktıya kopyalar. Bu nedenle, boşluklarda isimleri kırma şansı var.
Jonathan Leffler

16

rsync'in -R seçeneği beklediğinizi yapacaktır. Oldukça zengin özelliklere sahip bir dosya kopyalayıcıdır. Örneğin:

$ rsync -Rv src/prog.js images/icon.jpg /tmp/package/
images/
images/icon.jpg
src/
src/prog.js

sent 197 bytes  received 76 bytes  546.00 bytes/sec
total size is 0  speedup is 0.00

Örnek sonuçlar:

$ find /tmp/package
/tmp/package
/tmp/package/images
/tmp/package/images/icon.jpg
/tmp/package/src
/tmp/package/src/prog.js


1

Deneyin...

for f in src/*.js; do cp $f /tmp/package/$f; done

yani başlangıçta yaptığınız şey için ...

for f in `echo "src/prog.js images/icon.jpg"`; do cp $f /tmp/package/$f; done

veya

v="src/prog.js images/icon.jpg"; for f in $v; do cp $f /tmp/package/$f; done

İhtiyacın yok echoya da $vburada. Ayrıca, ilgili dizin hedefte yoksa bu yöntem başarısız olacaktır.
Weijun Zhou
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.