utilitário shell para verificar se o diretório é um ancestral de um arquivo

3

Como posso verificar se um determinado arquivo regular do caminho f é um descendente de um diretório do caminho d . Se não fosse por links simbólicos, gostaria apenas de verificar se d (com uma barra final) é o prefixo para f . Agora, com links simbólicos, isso fica um pouco mais complicado, pois eu posso encontrar os caminhos físicos dos ancestrais de f e comparar cada um deles com o caminho físico de d . No entanto, acredito que possa haver um utilitário do usuário para isso, existe um?

    
por Adrian Panasiuk 01.09.2010 / 00:04

2 respostas

4
  1. Se os ancestrais de um arquivo forem definidos como o diretório que o contém e os ancestrais desse diretório, ou seja, os descendentes de um diretório são suas entradas e (para as entradas que são diretórios) seus próprios descendentes:

    Assumindo que $f é o caminho de um arquivo regular (e não o caminho de um link simbólico), você pode encontrar o diretório “real” que o contém com $(cd -- "$(dirname "$f")" && command -p pwd) . Da mesma forma, encontre o local "real" do diretório $d com $(cd -- "$d" && command -p pwd) . No bash / ksh / zsh, você pode substituir command -p pwd por pwd -P .

    Se $f pode ser um link simbólico, é mais complicado. Alguns sistemas têm um comando readlink , por exemplo, você poderia usar $(dirname "$(readlink -f -- "$f")) com os coreutils GNU razoavelmente recentes, mas observe que existem outros sistemas com um comando readlink incompatível ou nenhum.

    Observe que o arquivo pode ser movido entre a hora em que você faz a verificação e a hora em que você usa o resultado. Há também casos de canto em que a pergunta não tem uma resposta sim / não clara, como quando o caminho do diretório para o arquivo atravessa um ponto de montagem.

    Se tudo o que você quer saber é qual sistema de arquivos $f está ativado, execute df "$f" .

  2. Se os descendentes de um diretório $d forem definidos como os arquivos que podem receber um nome no formato $d/x1/x2/.../xn , em que xi pode ser diretórios ou links simbólicos:

    O teste desta propriedade requer uma travessia de toda a árvore de diretórios com raiz em $d , seguindo todos os links simbólicos. O seguinte comando deve fazer isso (aviso, digitado diretamente no navegador; requer o GNU find):

    [ -n "$(find -L "$d" -samefile "$f" -print -quit)" ]
    

    Se $f tiver links físicos, isso poderá acessar o arquivo $f por meio de um nome diferente. Se você precisar que o arquivo seja encontrado sob o nome $f , fica mais complicado; aqui está uma tentativa (novamente, digitado diretamente no navegador; requer GNU find e GNU grep; não assume novas linhas nos nomes dos arquivos):

    f_directory="$(cd -- "$(dirname "$f")" && command -p pwd)"
    f_truename="$f_directory/$(basename "$f")"
    [ -n "$(find -L "$(cd "$d" && command -p pwd)" -exec readlink -f \; |
            grep -F -q -x "$f_truename")" ]
    

    Independentemente da definição exata escolhida, essa propriedade não é muito robusta, pois você pode alterar seu valor adicionando ou removendo um link simbólico profundo abaixo de $d .

por 01.09.2010 / 00:37
1

Meu comando 'ls' tem sinalizador "--dereference-command-line-symlink-to-dir" que mostra o caminho completo para o arquivo. Este 'ls' é do GNU coreutils 6.9.

    
por 01.09.2010 / 01:32