Linux / Bash: Criar links macios relativos a arquivos na árvore de diretórios?

1

Gostaria de criar links para todos os arquivos em uma árvore de diretórios. O que significa, crie a mesma estrutura de diretório e faça os links neles para o respectivo subdiretório no diretório original.

Isso pode ser feito com

cp -R -s ../foo .

Mas - isso precisa de um caminho absoluto. Então, um pouco

cp -R -s 'readlink -e ../foo' 'readlink -e .'

Gostaria que os links resultantes fossem relativos.

Existe alguma maneira fácil? Por exemplo. algum script ou programa especializado para isso.

    
por Ondra Žižka 23.11.2014 / 18:22

1 resposta

0

Este script deve fazer o que você quiser. É um pouco mais complexo do que você poderia esperar, porque precisa ser capaz de lidar com nomes arbitrários de arquivos e diretórios. Incluindo nomes com novas linhas, espaços em branco e caracteres globbing. Isso deve funcionar em qualquer nome que você der.

#!/usr/bin/env bash

sourceDir="$1"
targetDir="."

## The name of the source directory without its path
## First, we need to strip the trailing '/' if present.
sourceDir="${sourceDir%/}"
sourceName="${sourceDir##*/}"

## Find all files and directories in $source. -print0
## is needed to deal with names with newlines
find "$sourceDir" -mindepth 1 -print0 |
        ## Read eacch file/dir found into $f. IFS= ensures
        ## we can deal with whitespace correctly and -d ''
        ## lets 'read' read null-separated values. The -r
        ## ensures that backspaces don't have special meaning. All
        ## this to be certain that this will work on arbitrary file names. 
        while IFS= read -r -d '' f; do
                ##
                name="${f##$sourceDir}"
                ## Build the relative path for the symlink
                relname=$(perl -le '$ARGV[0]=~s|/[^/]+|/..|g; 
                            $ARGV[0]=~s|../..$|$ARGV[1]/$ARGV[2]|; 
                            print $ARGV[0]' "$f" "$sourceName" "$name")
                ## If this is a directory, create it
                if [ -d "$f" ]; then
                        mkdir -p "$targetDir/$name"
                ## If a file, link to it. 
                else
                        ln -s "$relname" "$targetDir/$name"
                fi
        done

Salve o script e torne-o executável e, em seguida, cd em seu diretório de destino e execute o script com o diretório de origem como um argumento. Por exemplo, para duplicar o diretório ../target no diretório atual, você executaria:

foo.sh  ../target/
    
por 24.11.2014 / 02:40