Bagaimana cara menyalin struktur folder dan membuat tautan simbolis ke file?

21

Saya memiliki SUMBER folder yang berisi beberapa folder sub-level, masing-masing dengan file sendiri.

Saya ingin menyalin folder ini dalam folder SALINAN baru di mana saya perlu menyalin struktur direktori tetapi menyimpan file sebagai tautan simbolis ke file asli di SOURCE dan subfoldernya.

Antonello
sumber
1
Lihat juga stackoverflow.com/q/1240636/905686 .
user905686
GNU Stow agak melakukan ini.
Kusalananda

Jawaban:

27

Inilah solusinya pada Linux dan Cygwin yang tidak tertanam:

cp -as SOURCE/ COPY

Perhatikan bahwa SOURCE harus menjadi jalur absolut dan memiliki garis miring. Jika Anda ingin memberikan jalur relatif, Anda dapat menggunakan

cp -as "$(pwd)/SOURCE/" COPY
roaima
sumber
Berfungsi sempurna, terima kasih. Hanya sebuah catatan .. SUMBER harus diberikan dengan jalur penuh (COPY dapat diberikan secara relatif jika ada yang mau)
Antonello
Bagaimana membuatnya berfungsi jika direktori sumber akan terus diperbarui dengan folder baru dan file baru di dalamnya? Akankah symlinks ke mereka secara otomatis dibuat di direktori tujuan dalam struktur folder yang benar?
SexyBeast
@AttitudeMonger Tidak, perintah seperti cp hanya membuat tautan sekali saja (seperti yang Anda lihat dari hasilnya). Untuk memperbarui tujuan secara otomatis Anda harus memantau direktori sumber untuk perubahan.
user905686
Apakah ini dapat dilakukan untuk membuat tautan relatif?
ctrl-alt-delor
@ Richard jika SOURCE adalah jalur relatif maka saya pikir begitu. Cobalah dan jika ini tidak berhasil, saya sarankan Anda ingin mengajukan pertanyaan baru. Referensi yang satu ini dengan segala cara.
roaima
6

Setidaknya ada 2 utilitas standar untuk membangun pohon direktori bayangan dari pohon yang ada, jadi tidak perlu menulis kode di sini.

Pertama ada lndir(1)dari xutils-devpaket. Ini menggunakan symlink ke file. Dari halaman manual:

NAME
   lndir  -  create a shadow directory of symbolic links to another
             directory tree
SYNOPSIS
   lndir [ -silent ] [ -ignorelinks ] [ -withrevinfo ] fromdir [ todir ]

Alternatif yang mungkin lebih baik adalah dengan menggunakan cpopsi yang tepat seperti yang disarankan oleh jawaban yang diterima. Saya hanya akan memberikan beberapa detail yang lebih bermanfaat:

cp -al /src/dir /dest/dir    # hard-links to leaf-files
cp -as /src/dir /dest/dir    # symlinks to leaf-files

Jika Anda tidak peduli tentang mempertahankan semua atribut (kepemilikan / izin, waktu) ganti aopsi (setara dengan -dr --preserve=all) dengan r(hanya rekursif):

cp -rl /src/dir /dest/dir    # hard-links to leaf-files
cp -rs /src/dir /dest/dir    # symlinks to leaf-files
diri sendiri
sumber
lndirjuga tersedia sebagai skrip shell di sini jika tidak diinstal: opensource.apple.com/source/X11/X11-0.46.4/lndir.sh?txt
Lenar Hoyt
2

Anda dapat mencoba beberapa perintah find seperti ini:

mkdir FULL-PATH-TO-COPY
cd SOURCE
find . \( ! -regex '\.' \) -type d -exec mkdir FULL-PATH-TO-COPY/{} \;
find * -type f -exec ln -s `pwd`/{} FULL-PATH-TO-COPY/{} \;
pichogve
sumber
1

Sesuatu seperti ini akan melakukan apa yang Anda butuhkan.

#!/bin/bash
#
SOURCE="$1" COPY="$2"
cd "$SOURCE"
find . |
    sed 's!^\./!!' |
    while IFS= read ITEM
    do
        test -d "$ITEM" && { mkdir -p "$COPY/$ITEM"; continue; }
        BASE="${FILE%\/*}"
        ( cd "$COPY/$BASE" && ln -s "$SOURCE/$ITEM" )
    done

Direktori dibuat di pohon COPY target. Yang lainnya disinkronkan kembali ke jalur absolut dalam pohon SUMBER. Pastikan bahwa SUMBER dan SALINAN ditentukan sebagai jalur absolut (dimulai dengan /).

Jika Anda memiliki pohon besar untuk disalin dan Anda ingin laporan kemajuan per-direktori, Anda bisa menambahkan echo "$ITEM" >&2;sebelum mkdirperintah.

(Saya melihat cpdan cpiotetapi sepertinya tidak ada pilihan untuk menghubungkan ke sumber dengan tautan simbolik.)

roaima
sumber
1
Komentar "tes baris 9" mungkin terkait dengan ksh pada AIX yang menginginkan tanda titik koma untuk menutup daftar yang ditutup kurung:{ mkdir -p "$COPY/$ITEM"; continue; }
Jeff Schaller
@JeffSchaller terima kasih. Saya tidak menulis kshskrip ... tetapi sepertinya itu perlu bashjuga. Memperbaiki
roaima
0

Jika tidak ada dir kosong di SOURCE yang perlu disalin

find /full/path/to/SOURCE -type f -exec cp -t COPY --parents -s {} +
mv COPY/full/path/to/SOURCE COPY
rm -r COPY/full
Costas
sumber
1
Karena Anda cptetap menganggap GNU , mengapa tidak cp -as?
Gilles 'SO- stop being evil'
0

Saya akan mulai dengan memecah perl:

#!/usr/bin/perl

use strict;
use warnings;
use File::Find;

my $src_dir = "/full_path/to/dir";
my $tgt_dir = "/path/to/new/location";

sub link_or_mkdir {

    #current file is directory
    if (-d) {
        #extract the path
        my $newpath = $File::Find::dir;
        #change the path so 'old' and 'new' are swapped
        $newpath =~ s,^$src_dir,$tgt_dir,g;
        #print the command to make a new dir (doesn't actually do it)
        print "mkdir -p $newpath\n";
    }
    if (-f) {
        my $new_file = $File::Find::name;
        #change the path so 'old' and 'new' are swapped
        $new_file =~ s,^$src_dir,$tgt_dir,g;
        #print the symlink command
        print "ln -s $File::Find::name $new_file\n";
    }
}

find( \&link_or_mkdir, $tgt_dir );

File::Findadalah modul yang berguna yang memungkinkan Anda untuk menjalankan subrutin tertentu pada file apa pun dalam pohon direktori. Dalam hal ini, sub memeriksa apakah itu direktori - dan jika itu, apakah mkdirfile atau - dalam hal ini apakah itu symlink.

Sobrique
sumber
-1

Sepertinya Anda mencari sesuatu seperti alat rsnapshot; itu membuat salinan direktori arbitrer dan menggunakan hardlink jika memungkinkan. (Lihat halaman manual untuk melihat apakah itu cocok.)

Janis
sumber
Tidak, pertanyaannya secara eksplisit menanyakan symlinks dan rsnapshot menggunakan hardlinks (karena ini adalah alat cadangan dan file-file tersebut harus disimpan walaupun dihapus dari direktori sumber).
user905686