Pertanyaan Bagaimana cara menyalin hanya atribut file (metadata) tanpa isi sebenarnya dari file?


Saya sudah menyalin file terabyte dengan rsync tapi saya lupa menggunakannya --archive untuk melestarikan atribut khusus file.

Saya mencoba mengeksekusi rsync lagi kali ini dengan --archive tapi itu jauh lebih lambat dari yang saya harapkan. Apakah ada cara mudah untuk melakukan ini lebih cepat dengan hanya menyalin metadata secara rekursif?


16
2017-08-12 08:39


asal


Dengan "metadata" maksud Anda izin file dan kepemilikan file atau hal yang lebih rumit seperti atribut file yang diperluas? - Marcel Stimberg
Filesystem tempat file sumber berada dipasang secara lokal atau tidak? - enzotib
menurut metadata Maksud saya izin dan perangko waktu. stempel waktu sangat penting bagi saya. - Mohammad
filsystem baik di sumber dan tujuan dipasang secara lokal. - Mohammad


Jawaban:


Oke, Anda dapat menyalin pemilik, grup, izin, dan stempel waktu menggunakan --reference parameter ke chown, chmod, touch. Berikut ini skrip untuk melakukannya

#!/bin/bash
# Filename: cp-metadata

myecho=echo
src_path="$1"
dst_path="$2"

find "$src_path" |
  while read src_file; do
    dst_file="$dst_path${src_file#$src_path}"
    $myecho chmod --reference="$src_file" "$dst_file"
    $myecho chown --reference="$src_file" "$dst_file"
    $myecho touch --reference="$src_file" "$dst_file"
  done

Anda harus menjalankannya sudo (untuk memungkinkan chown) dan dengan dua parameter: direktori sumber dan tujuan. Skrip hanya menggemakan apa yang akan dilakukannya. Jika puas mengubah garis myecho=echo dengan myecho=.


14
2017-08-12 10:55



Ya, itulah yang saya butuhkan: - referensi dalam chmod. Terima kasih. Dan saya sangat menghargai jika ada yang bisa memperkenalkan sesuatu seperti chmod - referensi untuk menyalin perangko waktu. - Mohammad
@Mohammad: untuk itu Anda bisa menggunakannya touch --reference=otherfile file. Diperbarui jawabannya - enzotib
Itu hebat. Sebenarnya saya sedang membaca manual sentuh sekarang ;-) - Mohammad
Sekedar catatan: touch dengan desain hanya mengubah modifikasi dan waktu akses, waktu "pembuatan" tidak terpengaruh. (Saya pikir ext2 / 3 tidak mendukung mengubah ctime, tetapi mungkin penting jika Anda menggunakan NTFS atau sejenisnya). - Amro
Jika Anda hanya ingin mengubah metadata ada file dan tidak perlu memastikan keberadaan file, tambahkan a -c beralih ke touch perintah untuk menghentikannya membuat file kosong di $dst_path. - Synchro


Memperlakukan pertanyaan sebagai "rsync hanya memiliki metadata untuk disalin, jadi mengapa itu sangat lambat, dan bagaimana saya bisa membuatnya lebih cepat?":

rsync biasanya menggunakan mtimes yang sama sebagai heuristik untuk mendeteksi dan melewati file tidak berubah. Tanpa --archive (khusus, tanpa --times) file tujuan 'mtimes tetap diatur ke waktu Anda rsync-ed mereka, sementara sumber file' mtimes tetap utuh (mengabaikan tipuan manual oleh Anda). Tanpa jaminan eksternal dari Anda bahwa isi file sumber 'tidak berubah, rsync harus menganggap mereka mungkin memiliki dan karenanya harus mengeceknya dan / atau menyalinnya kembali ke tujuan. Ini, ditambah fakta itu --whole-file tersirat untuk lokal-> sinkronisasi lokal, membuat rsync tanpa --times kurang lebih setara dengan cp untuk sinkronisasi lokal.

Asalkan memperbarui konten file tujuan dapat diterima, atau jika file sumber tidak disentuh sejak salinan asli, Anda harus mencari rsync --archive --size-only lebih cepat daripada rsync yang naif.

Jika ragu tentang apa rsync adalah menyalin yang memakan waktu sangat lama, rsync --archive --dry-run --itemize-changes ... memberitahu Anda secara mendalam, jika singkat, detail.


5
2018-06-14 16:41



Info yang sangat berguna. --archive --size-only adalah kombinasi yang hebat. Tidak hanya mencegah recopying file yang sudah ada di tujuan, tetapi juga akan memperbarui metadata mereka. Ini tidak terduga bagi saya, karena halaman manual rsync menggambarkan --size-only sebagai "melewatkan" file yang ukurannya cocok. Ternyata itu hanya melompati salinan, tetapi masih akan menyinkronkan metadata. Ideal. - Chad von Nau


PERINGATAN: Tanpa solusi khusus, GNU cp --attributes-only akan memotong file tujuan, setidaknya di Precise. Lihat hasil edit di bawah ini.

Asli:

Dalam situasi ini Anda mungkin ingin GNU cp --attributes-only pilihan, bersama dengan --archive, karena ini mencoba dan menguji kode, apakah semua atribut filesystem-agnostic dan tidak mengikuti symlinks (mengikutinya bisa menjadi buruk!):

cp --archive --attributes-only /source/of/failed/backup/. /destination/

Seperti file, cp aditif dengan atribut diperpanjang: jika kedua sumber dan tujuan telah memperluas atribut itu tambah atribut tambahan sumber ke tujuan (daripada menghapus semua xattr tujuan terlebih dahulu). Sementara ini mencerminkan bagaimana cp berperilaku jika Anda menyalin file ke pohon yang sudah ada, mungkin tidak seperti yang Anda harapkan.

Perhatikan juga bahwa jika Anda tidak mempertahankan tautan keras pada kali pertama rsync tetapi ingin melestarikan mereka sekarang cp  biasa perbaiki itu untukmu; Anda mungkin terbaik dari rerunning rsync dengan opsi yang tepat (lihat saya jawaban lainnya) dan bersabar.

Jika Anda menemukan pertanyaan ini sambil mencari dengan sengajapisahkan dan gabungkan kembali metadata / isi file, maka Anda mungkin ingin melihatnya metastore yang ada di repositori Ubuntu.

Sumber: GNU coreutils manual


Diedit untuk menambahkan:

cp dari GNU coreutils > = 8.17 dan di atas akan berfungsi seperti yang dijelaskan, tetapi coreutils <= 8.16 akan memotong file saat memulihkan metadata mereka. Jika ragu, jangan gunakan cp dalam situasi ini; menggunakan rsync dengan pilihan yang tepat dan / atau bersabar.

Saya tidak akan merekomendasikan ini kecuali Anda sepenuhnya memahami apa yang Anda lakukan, tetapi sebelumnya GNU cp dapat dicegah dari memotong file menggunakan Trik LD_PRELOAD:

/*
 * File: no_trunc.c
 * Author: D.J. Capelis with minor changes by Zak Wilcox
 *
 * Compile:
 * gcc -fPIC -c -o no_trunc.o no_trunc.c
 * gcc -shared -o no_trunc.so no_trunc.o -ldl
 *
 * Use:
 * LD_PRELOAD="./no_trunc.so" cp --archive --attributes-only <src...> <dest>
 */

#define _GNU_SOURCE
#include <dlfcn.h>
#define _FCNTL_H
#include <bits/fcntl.h>

extern int errorno;

int (*_open)(const char *pathname, int flags, ...);
int (*_open64)(const char *pathname, int flags, ...);

int open(const char *pathname, int flags, mode_t mode) {
        _open = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open");
        flags &= ~(O_TRUNC);
        return _open(pathname, flags, mode);
}

int open64(const char *pathname, int flags, mode_t mode) {
        _open64 = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open64");
        flags &= ~(O_TRUNC);
        return _open64(pathname, flags, mode);
}

4
2018-05-28 01:39



errorno seharusnya errnobenar? - enzotib
Sebuah tes cepat menghapusnya tampaknya berfungsi, jadi saya kira saya mengabadikan redundansi / kesalahan di asli, tetapi semua orang akan berada di coreutils baru sekarang. - ZakW


Di transfer lokal, ketika sumber dan tujuan berada di sistem file yang dipasang secara lokal, rsync akan selalu menyalin seluruh konten file. Untuk menghindari ini, Anda dapat menggunakan

rsync -a --no-whole-file source dest

2
2017-08-12 10:25



Saya mencoba rsync dengan --no-whole-file dan --progress dan saya masih dapat melihat proses penyalinan (sekitar 30 MB / dtk); jadi saya kira itu belum cukup cepat. Saya kehilangan harapan pada rsync ... - Mohammad


Saya harus melakukan ini dari jarak jauh ke komputer lain sehingga saya tidak bisa menggunakan - referensi

Saya menggunakan ini untuk membuat skrip ...

find -printf "touch -d \"%Tc\" \"%P\"\n" >/tmp/touch.sh

Tapi pastikan tidak ada nama file dengan "di dalamnya dulu ...

find | grep '"'

Kemudian salin touch.sh ke komputer jarak jauh Anda, dan jalankan ...

cd <DestinationFolder>; sh /tmp/touch.sh

Ada juga opsi di temukan-printf untuk mencetak pengguna, nama grup jika Anda ingin menyalinnya.


0
2017-10-20 12:32