Yinelenen kopyalamak istediğiniz alt dizinleri ve dosyaları içeren büyük bir dizin var.
cp
Kopyalama işlemini dosya boyutuna göre yapması gerektiğini söylemenin herhangi bir yolu var mı , böylece en küçük dosyalar önce kopyalanıyor mu?
Yinelenen kopyalamak istediğiniz alt dizinleri ve dosyaları içeren büyük bir dizin var.
cp
Kopyalama işlemini dosya boyutuna göre yapması gerektiğini söylemenin herhangi bir yolu var mı , böylece en küçük dosyalar önce kopyalanıyor mu?
Yanıtlar:
Bu, tüm işi tek seferde yapar - tüm alt dizinlerde, dosya adı sorunları olmadan tek bir akışta. Sahip olduğunuz her dosyayı en küçükten en büyüğe kopyalar. Henüz mkdir ${DESTINATION}
mevcut değilse yapmanız gerekir .
find . ! -type d -print0 |
du -b0 --files0-from=/dev/stdin |
sort -zk1,1n |
sed -zn 's/^[^0-9]*[0-9]*[^.]*//p' |
tar --hard-dereference --null -T /dev/stdin -cf - |
tar -C"${DESTINATION}" --same-order -xvf -
Ne var biliyor musun? Bunun yapmadığı şey boş alt dizinlerdir. Bu boru hattı üzerinden biraz yeniden yönlendirme yapabilirdim, ama bu sadece gerçekleşmeyi bekleyen bir yarış durumu. En basit olanı muhtemelen en iyisidir. Bunu daha sonra yapın:
find . -type d -printf 'mkdir -p "'"${DESTINATION}"'/%p"\n' |
. /dev/stdin
Veya Gilles, dizin izinlerini korumak için cevabında çok iyi bir noktaya değindiğinden, denemeliyim. Bunun yapacağını düşünüyorum:
find . -type d -printf '[ -d "'"${DESTINATION}"'/%p" ] ||
cp "%p" -t "'"${DESTINATION}"'"\n' |
. /dev/stdin
Bahse girerim ki bu mkdir
zaten her zamankinden daha hızlı .
İşte hızlı ve kirli bir yöntem kullanarak rsync
. Bu örnek için 10 MB altındaki herhangi bir şeyin "küçük" olduğunu düşünüyorum.
İlk önce sadece küçük dosyaları aktarın:
rsync -a --max-size=10m srcdir dstdir
Ardından kalan dosyaları aktarın. Önceden aktarılan küçük dosyalar değiştirilmedikçe yeniden kopyalanmaz.
rsync -a srcdir dstdir
itibaren man 1 rsync
--max-size=SIZE
This tells rsync to avoid transferring any file that is larger
than the specified SIZE. The SIZE value can be suffixed with a
string to indicate a size multiplier, and may be a fractional
value (e.g. "--max-size=1.5m").
This option is a transfer rule, not an exclude, so it doesn’t
affect the data that goes into the file-lists, and thus it
doesn’t affect deletions. It just limits the files that the
receiver requests to be transferred.
The suffixes are as follows: "K" (or "KiB") is a kibibyte
(1024), "M" (or "MiB") is a mebibyte (1024*1024), and "G" (or
"GiB") is a gibibyte (1024*1024*1024). If you want the multi‐
plier to be 1000 instead of 1024, use "KB", "MB", or "GB".
(Note: lower-case is also accepted for all values.) Finally, if
the suffix ends in either "+1" or "-1", the value will be offset
by one byte in the indicated direction.
Examples: --max-size=1.5mb-1 is 1499999 bytes, and
--max-size=2g+1 is 2147483649 bytes.
Tabii ki, dosya-dosya aktarım sırası kesinlikle en küçükten en büyüğe değil, ama ihtiyaçlarınızın ruhunu karşılayan en basit çözüm olabileceğini düşünüyorum.
--copy-dest=DIR
Ve / veya --compare-dest=DIR
bence çok daha iyi yapardın . Sadece cevabımı --hard-dereference
gönderdikten tar
sonra kendi cevabımı gönderdikten sonra kendimi eklemek zorunda olduğumu biliyorum . Ben rsync
aslında başkaları ile yerel dosya sistemlerine daha spesifik davranıyor düşünüyorum - USB anahtarları ile kullanırdım ve bir bant genişliği sınırı belirlemezseniz otobüs sel olurdu. Sanırım bu ikisinden birini kullanmalıydım.
cp
Doğrudan değil , bu yeteneklerinin çok ötesinde. Ancak cp
, dosyaları doğru sırayla çağırmayı düzenleyebilirsiniz .
Zsh, glob niteleyici ile dosyaları boyuta göre sıralamaya izin verir . İşte hangi kopyalar altından boyutu artan sırada dosyaları zsh snippet'ine /path/to/source-directory
altındakiler için /path/to/destination-directory
.
cd /path/to/source-directory
for x in **/*(.oL); do
mkdir -p /path/to/destination-directory/$x:h
cp $x /path/to/destination-directory/$x:h
done
Bir döngü yerine, zcp
işlevi kullanabilirsiniz . Ancak önce şifreli bir satırda yapılabilecek hedef dizinleri oluşturmanız gerekir.
autoload -U zmv; alias zcp='zmv -C'
cd /path/to/source-directory
mkdir **/*(/e\''REPLY=/path/to/destination-directory/$REPLY'\')
zcp -Q '**/*(.oL)' '/path/to/destination-directory/$f'
Bu, kaynak dizinlerin sahipliğini korumaz. İsterseniz, cpio
veya gibi uygun bir kopyalama programına kaydolmanız gerekir pax
. Bunu yaparsanız, aramanıza cp
veya zcp
ek olarak aramanıza gerek yoktur .
cd /path/to/source-directory
print -rN **/*(^.) **/*(.oL) | cpio -0 -p /path/to/destination-directory
Bunu cp -r
doğrudan yapmanın bir yolu olduğunu sanmıyorum . Bir sihirbaz find
/ awk
çözüm bulmadan önce belirsiz bir süre olabileceğinden , işte hızlı bir perl betiği:
#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);
use File::Find;
use File::Basename;
die "No (valid) source directory path given.\n"
if (!$ARGV[0] || !-d -r "/$ARGV[0]");
die "No (valid) destination directory path given.\n"
if (!$ARGV[1] || !-d -w "/$ARGV[1]");
my $len = length($ARGV[0]);
my @files;
find (
sub {
my $fpath = $File::Find::name;
return if !-r -f $fpath;
push @files, [
substr($fpath, $len),
(stat($fpath))[7],
]
}, $ARGV[0]
);
foreach (sort { $a->[1] <=> $b->[1] } @files) {
if ($ARGV[2]) {
print "$_->[1] $ARGV[0]/$_->[0] -> $ARGV[1]/$_->[0]\n";
} else {
my $dest = "$ARGV[1]/$_->[0]";
my $dir = dirname($dest);
mkdir $dir if !-e $dir;
`cp -a "$ARGV[0]/$_->[0]" $dest`;
}
}
Bunu kullan: ./whatever.pl /src/path /dest/path
Argümanların her ikisi de mutlak yol olmalıdır ; ~
veya kabuğun mutlak bir yola genişlettiği herhangi bir şey iyidir.
Üçüncü bir argüman eklerseniz (değişmez bir şey dışında herhangi bir şey 0
), kopyalamak yerine, ne yapacağının bir raporunu standart olarak yazdırır;
4523 /src/path/file.x -> /dest/path/file.x
12124 /src/path/file.z -> /dest/path/file.z
Bunların boyuta göre artan sırada olduğuna dikkat edin.
cp
Eğer anahtarlar (Sadece kullanılan ile istediğinizi yapabilirsiniz, böylece hat 34 üzerinde komut, bir hazır kabuk komut -a
tüm özelliklerini korumak için).
File::Find
ve File::Basename
her ikisi de çekirdek modüllerdir, yani perl'in tüm kurulumlarında kullanılabilirler.
cp - copy smallest files first?
ancak yazının başlığı copy smallest files first?
Her neyse, seçenekler asla zarar görmedi benim felsefem, ama yine de, sen ve David kullanılan cp
tek sensin ve onu çeken tek kişisin.
cp
, (çapraz platform odaklı) perl'de * nix dosya özelliklerini korumanın en basit yoluydu. Tarayıcı çubuğunuzun söylemesinin cp -
nedeni, seçilen etiketlerin en popüler öğelerinin gerçek başlığın önüne eklenmiş olduğu (IMO goofy) SE özelliğinden kaynaklanmaktadır.
pearl
buradaki ağaç işlerinden çıktığını görmüyorsunuz .
başka bir seçenek du çıktı ile cp kullanmak olacaktır:
oldIFS=$IFS
IFS=''
for i in $(du -sk *mpg | sort -n | cut -f 2)
do
cp $i destination
done
IFS=$oldIFS
Bu yine de tek bir satırda yapılabilir, ama okuyabilmeniz için bölüyorum