Como encontrar intermediários na recursão de links simbólicos?

1

Existe uma alternativa readlink -f / realpath não recursiva, que produz destinos de links simbólicos absolutos? Uma solução mais compatível com POSIX também é bem-vinda.

Eu tenho um bloco de funções no meu script de shell da seguinte forma:

set FILES
# addFile adds a file to the FILES list. If file is a symlink,
# it will also find and add the destination.
addFile() {
    file="$1"
    # Check if file is already included in list
    echo "$FILES" | grep -q "$file" && return
    FILES="$FILES $file"
    if [ -L $file ]; then
        addFile $(realpath $file)
        #addFile $(readlink $file)
    fi
}

Estou usando essa função em um script que está coletando arquivos binários e de bibliotecas de todo o sistema de arquivos. Mas eu prevejo um problema neste código:

  1. Na minha primeira tentativa, usei readlink , mas isso retornou caminhos de resolução de links simbólicos em relação ao $file , portanto, quaisquer ações executadas nesses caminhos falharão. (Agora comentado, mas ainda no código) (Veja edição menor abaixo)
  2. Depois disso, usei realpath , como sugerido por man readlink . Quase funciona.

Agora, as ações que eu quero realizar podem funcionar. No entanto, no resultado final estou copiando todos os binários, bibliotecas e links simbólicos em um initramfs. Se houver links simbólicos recursivos, somente o nível superior e o destino serão incluídos, não os intermediários. Assim, quebrando o symlink.

Criei um violino para demonstrar o problema. link-to-link1 aponta para link1 , que aponta para file1 . No resultado final link1 está faltando e link-to-link1 está quebrado.

Editar; esclarecer a questão

Ao executar a função acima no seguinte conjunto de links simbólicos:

# Contents of ~/test/src
file0
file1
link0 -> file0
link0.1 -> file0
link1 -> file1
link-to-link1 -> link1

Com:

copy="link-to-link1 link0 link0.1"
for sf in $copy; do
    addFile ~/test/src/$sf
done;
cp -av $FILES ~/test/dst

Você descobrirá que apenas os 3 links de $copy e 2 arquivos são copiados. No entanto, o link intermediário link1 está faltando e link-to-link1 está corrompido.

Gostaria que o script também encontrasse link1 . Tendo em mente que no ambiente onde este script é executado, a localização dos arquivos e links simbólicos deve ser absoluta.

Edição menor

Adicione outro violino para demonstrar a falha de caminhos relativos, usando readlink . Apenas os links simbólicos são copiados e os destinos estão faltando.

    
por Tim 24.05.2018 / 18:56

1 resposta

2

Se bem entendi, para o exemplo dado, você deseja link1 para o arquivo link-to-link1 . Que você pode usar GNU find -printf e %l :

$ find . -type l -printf '%p -> %l\n'
./link0.1 -> file0
./link1 -> file1
./link0 -> file0
./link-to-link1 -> link1

Como o caminho absoluto de link1 é necessário como saída para /path/to/link-to-link1 , talvez cd para o diretório que contém link-to-link1 e execute readlink / realpath em sucessão:

(
cd "$(dirname "$file")"
realpath -s "$(readlink "$file")"
)

realpath -s não resolve links simbólicos, mas imprime o caminho absoluto.

Por exemplo:

~ file=/tmp/foo/link-to-link1
~ (cd "$(dirname "$file")"; realpath -s "$(readlink "$file")")
/tmp/foo/link1

Isso também funcionará para links para caminhos absolutos:

~ file=/tmp/foo/link2
~ ln -sfv /tmp/foo/link1 "$file"
'/tmp/foo/link2' -> '/tmp/foo/link1'
~ (cd "$(dirname "$file")"; realpath -s "$(readlink "$file")")
/tmp/foo/link1
    
por 25.05.2018 / 09:20