ProHoster > Blog > yönetim > cp komutu: *nix'teki dosya klasörlerini doğru şekilde kopyalamak
cp komutu: *nix'teki dosya klasörlerini doğru şekilde kopyalamak
Bu makale, kullanımıyla ilgili bazı açık olmayan şeyleri ortaya çıkaracaktır. joker kopyalarken belirsiz komut davranışı cp kopyalama sırasında ve ayrıca çok sayıda dosyayı atlamadan veya çökmeden doğru şekilde kopyalamanıza olanak tanıyan yöntemler.
Diyelim ki /source klasöründeki her şeyi /target klasörüne kopyalamamız gerekiyor.
Akla gelen ilk şey şudur:
cp /source/* /target
Bu komutu hemen şu şekilde düzeltelim:
cp -a /source/* /target
Anahtar -a tüm niteliklerin, hakların kopyalanmasını ve özyinelemeyi ekleyecektir. Hakların tam olarak çoğaltılmasının gerekmediği durumlarda bir anahtar yeterlidir -r.
Kopyaladıktan sonra tüm dosyaların kopyalanmadığını göreceğiz; noktayla başlayan dosyalar şöyle:
.profile
.local
.mc
ve benzerleri.
Bu neden oldu?
Çünkü joker karakterler kabuk tarafından işlenir (bash tipik bir durumda). Varsayılan olarak bash, noktalarla başlayan tüm dosyaları gizli olarak değerlendirdiğinden yok sayar. Bu davranışı önlemek için davranışı değiştirmemiz gerekecek bash komutu kullanarak:
shopt -s dotglob
Bu davranış değişikliğinin yeniden başlatma sonrasında da devam etmesini sağlamak için klasörde bu komutla bir joker.sh dosyası oluşturabilirsiniz. /etc/profile.d (Belki de dağıtımınızda farklı bir klasör vardır).
Kaynak dizinde dosya yoksa, kabuk yıldız işaretinin yerine hiçbir şey koyamayacak ve kopyalama da bir hatayla başarısız olacaktır. Bu duruma karşı seçenekler var failglob и nullglob. ayarlamamız gerekecek failglobBu, komutun yürütülmesini engelleyecektir. nullglob eşleşme bulamayan joker karakterler içeren bir dizeyi boş bir dizeye (sıfır uzunluk) dönüştürdüğü için çalışmaz. cp hataya neden olacaktır.
Ancak klasörde binlerce veya daha fazla dosya varsa joker karakterler yaklaşımı tamamen terk edilmelidir. Gerçek şu ki bash joker karakterleri aşağıdaki gibi çok uzun bir komut satırına genişletir:
cp -a /souce/a /source/b /source/c …… /target
Komut satırının uzunluğunun bir sınırı vardır ve bunu şu komutu kullanarak öğrenebiliriz:
….
Maximum length of command we could actually use: 2089314
….
O halde joker karakterleri tamamen ortadan kaldıralım.
Hadi sadece yazalım
cp -a /source /target
Ve burada davranışın belirsizliğiyle karşı karşıyayız cp. /target klasörü yoksa ihtiyacımız olanı alacağız.
Ancak hedef klasör mevcutsa dosyalar /target/source klasörüne kopyalanacaktır.
/target klasörünü her zaman önceden silemeyiz çünkü ihtiyacımız olan dosyaları içerebilir ve örneğin hedefimiz, /target içindeki dosyaları /source'daki dosyalarla tamamlamaktır.
Kaynak ve hedef klasörler aynı şekilde adlandırılmışsa, örneğin, /source'dan /home/source'a kopyalıyorsak, o zaman şu komutu kullanabiliriz:
cp -a /source /home
Ve kopyalamadan sonra, /home/source içindeki dosyalar /source'daki dosyalarla desteklenecektir.
Bu mantıksal bir sorundur: Klasörler aynı şekilde adlandırılmışsa hedef dizine dosya ekleyebiliriz, ancak farklılarsa kaynak klasör hedefin içine yerleştirilecektir. Joker karakterler olmadan cp kullanarak dosyalar /source'dan /target'e nasıl kopyalanır?
Bu zararlı sınırlamayı aşmak için açık olmayan bir çözüm kullanıyoruz:
cp -a /source/. /target
DOS ve Linux'a aşina olanlar zaten her şeyi anlamışlardır: her klasörün içinde 2 görünmez klasör vardır "." ve mevcut ve daha yüksek dizinlere sözde klasör bağlantıları olan “..”.
Kopyalarken cp varlığını kontrol eder ve /target/ oluşturmaya çalışır.
Böyle bir dizin var ve /target
/source'daki dosyalar /target'e doğru şekilde kopyalandı.
O halde onu kalın bir çerçeveyle hafızanıza veya duvarınıza asın:
cp -a /source/. /target
Bu komutun davranışı açıktır. Milyonlarca dosyanız olsa da olmasa da, her şey hatasız çalışacaktır.
Bulgular
Kopyalamanız gerekiyorsa tüm dosyaları bir klasörden diğerine taşımak için joker karakterler kullanmıyoruz, bunun yerine bunları kullanmak daha iyidir cp kaynak klasörün sonunda bir nokta ile birleştirilir. Bu, gizli olanlar da dahil olmak üzere tüm dosyaları kopyalayacak ve milyonlarca dosya veya hiç dosya olmaması durumunda başarısız olmayacaktır.
Послесловие
vmspike benzer sonuca sahip bir komut sürümü önerdi: