วิธีคัดลอกเฉพาะไฟล์คุณลักษณะ (ข้อมูลเมตา) โดยไม่มีเนื้อหาจริงของไฟล์?


21

ฉันได้คัดลอกเทราไบต์ของไฟล์ด้วยrsyncแต่ฉันลืมที่จะใช้--archiveเพื่อรักษาคุณสมบัติพิเศษของไฟล์

ฉันพยายามดำเนินการrsyncอีกครั้งคราวนี้ด้วย--archiveแต่มันช้ากว่าที่ฉันคาดไว้ มีวิธีง่าย ๆ ที่จะทำเร็วขึ้นโดยเพียงแค่คัดลอกเมตาดาต้าซ้ำ?


ด้วย "ข้อมูลเมตา" คุณหมายถึงการอนุญาตไฟล์และการเป็นเจ้าของไฟล์หรือสิ่งที่ซับซ้อนกว่าเช่นคุณสมบัติไฟล์เพิ่มเติม?
Marcel Stimberg

ระบบไฟล์ที่ไฟล์ต้นฉบับอยู่นั้นถูกเมาท์หรือไม่?
enzotib

โดย metadata ฉันหมายถึงการอนุญาตและการประทับเวลา การประทับเวลามีความสำคัญอย่างยิ่งสำหรับฉัน
โมฮัมหมัด

ระบบไฟล์ทั้งในแหล่งที่มาและปลายทางติดตั้งในเครื่อง
โมฮัมหมัด

คำตอบ:


17

ตกลงคุณสามารถคัดลอกเจ้าของกลุ่มได้รับอนุญาตและการประทับเวลาโดยใช้--referenceพารามิเตอร์chown, ,chmod touchนี่คือสคริปต์ที่ต้องทำ

#!/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

คุณควรรันด้วยsudo(เพื่ออนุญาตให้ chown) และมีสองพารามิเตอร์: ไดเรกทอรีต้นทางและปลายทาง สคริปต์สะท้อนสิ่งที่มันจะทำเท่านั้น หากมีความพึงพอใจการเปลี่ยนแปลงบรรทัดด้วยmyecho=echomyecho=


1
ใช่นั่นคือสิ่งที่ฉันต้องการ: - อ้างอิงใน chmod ขอขอบคุณ. และฉันซาบซึ้งจริง ๆ ถ้าใครสามารถแนะนำ chmod - การอ้างอิงสำหรับการคัดลอกเวลาประทับ
โมฮัมหมัด

1
@Mohammad: touch --reference=otherfile fileการที่คุณสามารถใช้ อัปเดตคำตอบ
enzotib

เยี่ยมมาก จริงๆแล้วฉันกำลังอ่านคู่มือสัมผัสตอนนี้ ;-)
โมฮัมมัด

เพียงข้อสังเกต: touchโดยการออกแบบจะเปลี่ยนเฉพาะเวลาการแก้ไขและการเข้าถึงเท่านั้นเวลา "การสร้าง" จะไม่ได้รับผลกระทบ (ฉันคิดว่า ext2 / 3 ไม่สนับสนุนการเปลี่ยนเวลา แต่มันอาจสำคัญว่าคุณใช้ NTFS หรือไม่ชอบ)
Amro

ในกรณีที่คุณต้องการที่จะเปลี่ยนแปลงข้อมูลเมตาเพียงอย่างเดียวที่มีอยู่ไฟล์และไม่จำเป็นต้องให้ความมั่นใจกับการดำรงอยู่ของไฟล์ที่เพิ่ม-cสลับไปที่คำสั่งที่จะหยุดมันสร้างไฟล์ที่ว่างเปล่าในtouch $dst_path
ซิงโคร

5

คำเตือน: หากไม่มีวิธีแก้ปัญหาพิเศษ GNU cp --attributes-onlyจะตัดทอนไฟล์ปลายทางอย่างน้อยที่สุดใน Precise ดูการแก้ไขด้านล่าง

เดิม:

ในสถานการณ์นี้คุณอาจต้องการ--attributes-onlyตัวเลือกของ GNU cp ร่วมกับ--archiveซึ่งเป็นรหัสที่ได้ลองและทดสอบแล้วจะทำทุกอย่างที่ไม่เชื่อเรื่องระบบแฟ้มและไม่ทำตาม symlinks (ทำตามได้ไม่ดี!):

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

เช่นเดียวกับไฟล์cpเป็นสารเติมแต่งที่มีแอตทริบิวต์เพิ่มเติม: หากทั้งต้นทางและปลายทางมีแอตทริบิวต์ที่ขยายเพิ่มมันจะเพิ่มแอตทริบิวต์เพิ่มเติมของต้นทางไปยังปลายทาง (แทนที่จะลบ xattrs ทั้งหมดของปลายทางก่อน) แม้ว่าสิ่งนี้จะสะท้อนcpพฤติกรรมอย่างไรถ้าคุณคัดลอกไฟล์ลงในแผนผังที่มีอยู่ แต่อาจไม่ใช่สิ่งที่คุณคาดหวัง

นอกจากนี้โปรดทราบว่าหากคุณไม่ได้เก็บลิงก์ถาวรไว้ในครั้งแรกด้วยrsyncแต่ต้องการที่จะเก็บลิงก์ไว้ตอนนี้คุณcp จะไม่แก้ไขปัญหานั้นให้คุณ คุณน่าจะดีที่สุดเมื่อใช้rsyncตัวเลือกที่เหมาะสม (ดูคำตอบอื่น ๆของฉัน) และอดทน

หากคุณพบคำถามนี้ในขณะที่ต้องการแยกเนื้อหาเมตาดาต้า / ไฟล์ที่รวมกันใหม่โดยเจตนาแล้วคุณอาจต้องการดูmetastoreซึ่งอยู่ในที่เก็บของ Ubuntu

ที่มา: คู่มือ GNU coreutils


แก้ไขเพื่อเพิ่ม:

cpจาก GNU coreutils> = 8.17 ขึ้นไปจะทำงานตามที่อธิบายไว้ แต่ coreutils <= 8.16 จะตัดทอนไฟล์เมื่อเรียกคืนข้อมูลเมตา หากมีข้อสงสัยอย่าใช้cpในสถานการณ์นี้ ใช้rsyncกับตัวเลือกที่ถูกต้องและ / หรืออดทน

ฉันจะไม่แนะนำสิ่งนี้เว้นแต่คุณจะเข้าใจอย่างถ่องแท้ว่าคุณกำลังทำอะไร แต่ GNU ก่อนหน้านี้cpสามารถป้องกันการตัดทอนไฟล์โดยใช้เคล็ดลับ 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);
}

errornoควรจะerrnoใช่มั้ย
enzotib

การทดสอบแบบรวดเร็วลบดูเหมือนว่าจะใช้งานได้ดังนั้นฉันคิดว่าฉันคงความซ้ำซ้อน / ความผิดพลาดในต้นฉบับแต่ทุกคนจะได้รับ coreutils ที่ใหม่กว่าในตอนนี้
ZakW

แต่สิ่งที่คุณเรียกrsyncพร้อมกับตัวเลือกที่เหมาะสมเป็นคำตอบสำหรับคำถามอื่น ...
Jean Paul

5

การตอบคำถามเป็น "rsync มีเมทาดาทาที่จะคัดลอกเท่านั้นเหตุใดจึงช้าและฉันจะทำให้เร็วขึ้นได้อย่างไร":

rsyncมักจะใช้ mtimes เท่ากันเป็นฮิวริสติกในการตรวจจับและข้ามไฟล์ที่ไม่เปลี่ยนแปลง โดยไม่ต้อง--archive(โดยเฉพาะโดยไม่ต้อง--times) mtimes ของไฟล์ปลายทางจะถูกตั้งค่าเป็นเวลาที่คุณ rsync-ed ในขณะที่ mtimes ของไฟล์ต้นฉบับจะยังคงอยู่ (ไม่สนใจคุณด้วยตนเอง) หากไม่มีการรับรองจากภายนอกว่าเนื้อหาของไฟล์ต้นฉบับนั้นไม่มีการเปลี่ยนแปลง rsync จะต้องถือว่าพวกเขามีและดังนั้นจึงต้องทำการตรวจสอบพวกเขาและ / หรือคัดลอกไปยังปลายทางอีกครั้ง สิ่งนี้บวกกับความจริงที่บอก--whole-fileเป็นนัยสำหรับ local-> local syncs ทำให้rsyncโดยไม่--timesเทียบเท่ากับcpการซิงค์ในท้องถิ่น

โดยมีเงื่อนไขว่าการอัปเดตเนื้อหาของไฟล์ปลายทางนั้นเป็นที่ยอมรับหรือหากไฟล์ต้นฉบับนั้นไม่ถูกแตะต้องตั้งแต่การคัดลอกต้นฉบับคุณควรพบว่าrsync --archive --size-onlyเร็วกว่า rsync ที่ไร้เดียงสา

หากมีข้อสงสัยเกี่ยวกับสิ่งที่rsyncคัดลอกซึ่งใช้เวลานานมากให้rsync --archive --dry-run --itemize-changes ...บอกรายละเอียดที่ละเอียดถี่ถ้วน


1
ข้อมูลที่มีประโยชน์มาก - เก็บถาวร - ขนาดเท่านั้นเป็นคอมโบที่ยอดเยี่ยม ไม่เพียงป้องกันไฟล์ที่จัดเรียงใหม่ที่มีอยู่ในปลายทางแล้ว แต่ยังจะอัปเดตข้อมูลเมตาอีกด้วย นี่เป็นสิ่งที่ไม่คาดคิดสำหรับฉันเนื่องจากหน้าคนของ rsync อธิบาย - ขนาดเท่านั้นเป็นไฟล์ "ข้าม" ซึ่งมีขนาดตรงกัน ปรากฎว่ามันข้ามการคัดลอก แต่จะยังคงซิงค์ข้อมูลเมตา ในอุดมคติ.
ชาดฟอนเนา

2

ในการถ่ายโอนโลคัลเมื่อแหล่งที่มาและปลายทางอยู่บนระบบไฟล์ที่เมาท์แบบโลคัลrsyncจะคัดลอกเนื้อหาไฟล์ทั้งหมด เพื่อหลีกเลี่ยงปัญหานี้คุณสามารถใช้

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

ฉันลอง rsync ด้วย - ไม่มีทั้งไฟล์และ --progress และฉันยังสามารถเห็นความคืบหน้าในการคัดลอก (ประมาณ 30 MB / s); ดังนั้นฉันเดาว่ามันยังไม่เร็วพอ ฉันกำลังสูญเสียความหวังใน rsync ...
โมฮัมหมัด

ตัวเลือกนี้ใช้เพื่อบอกrsyncไม่ให้ใช้ทางลัดเมื่อไฟล์ต่าง ๆ อยู่ในโลคัลพา ธ แต่ไม่ได้ป้องกันrsyncการคัดลอกเนื้อหา
Jean Paul

1

ฉันต้องทำสิ่งนี้จากระยะไกลไปยังคอมพิวเตอร์เครื่องอื่นดังนั้นฉันจึงไม่สามารถใช้ - การอ้างอิง

ฉันใช้สิ่งนี้เพื่อสร้างสคริปต์ ...

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

แต่ให้แน่ใจว่าไม่มีชื่อไฟล์ใด ๆ "ในพวกเขาก่อน ...

find | grep '"'

จากนั้นคัดลอก touch.sh ไปยังคอมพิวเตอร์ระยะไกลของคุณแล้วเรียกใช้ ...

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

นอกจากนี้ยังมีตัวเลือกในการค้นหา -printf เพื่อพิมพ์ผู้ใช้ชื่อกลุ่มหากคุณต้องการคัดลอก


ขอขอบคุณสำหรับความคิดไปยัง) "เพียงแค่ใช้สคริปต์เชลล์" และ b) findการสร้างสคริปต์กล่าวว่าการใช้ ผมอยู่ในสถานการณ์เดียวกัน - ลืมที่จะคัดลอกคุณลักษณะต้นทางและปลายทางดิสก์มีอยู่แล้วในเครื่องที่แตกต่างและไม่ได้จริงๆต้องการกลับว่า
i336_
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.