como usar find + xargs para criar links simbólicos para arquivos selecionados enquanto mantém a árvore de diretórios relativa (usa gnu cp -s)

0

Estou tentando replicar arquivos selecionados de uma estrutura de diretórios como links simbólicos em um diretório duplicado, por exemplo,

de uma estrutura de diretórios como esta:

../1/a/data1.txt
../1/a/file1.txt
../1/a/b/file2.txt

faça isso:

../2/a/file1.txt -> ../../1/a/file1.txt
../2/a/b/file2.txt -> ../../2/a/b/file1.txt

Por exemplo, mantenha a árvore dir e pule arquivos que correspondam a vários padrões.

quando eu uso o GNU cp do diretório de destino (../2/a), substituindo os caminhos relativos, tudo funciona como eu quero, exceto que ele copia data1.txt:

gcp -rs $(cd ../..; pwd)/1/a/* $PWD/

mas quando eu uso isso em find + xargs para excluir certos arquivos,

find  -X -f $(cd ../..; pwd)/1/a \! -name '*data*' -type f | xargs -t -n1 -I % gcp -s -t $PWD/ %

Eu entendo isso:

../2/a/file1.txt -> ../1/a/file1.txt
../2/a/file2.txt -> ../1/a/b/file2.txt

por exemplo, a estrutura do diretório não está sendo replicada. Eu posso imaginar soluções tediosas, mas devo estar perdendo algo essencial na sintaxe de xargs. (Eu quero usar o find porque os arquivos antes e depois de certas datas recebem tratamentos diferentes).

minha solução era chamar subshell, construir caminhos, criar diretórios, criar links ... aproximadamente (por exemplo, não foi testado usando o exemplo aqui):

find $(cd ../..; pwd) -type f \! -name '*data*' -print0 | xargs -0 bash -c 
     'while [ -n "$1" ]; do
           TMP="${1%$(basename $1)}"; 
           mkdir -p "${TMP/1/2}";  
           gcp -s "$1" "${1/1/2}"; 
           shift;
      done;' "bash"

desde que isso foi chamado dentro de um script, antes do comando eu exportei os nomes de caminho relevantes ("1" e "2" aqui eram $ PATH1, $ PATH2; confuso neste exemplo b / c de $ 1 vs "1" e "2").

    
por esar 04.10.2018 / 08:44

1 resposta

1

Se você não copiar os diretórios recursivamente com o argumento -r , cp não criará diretórios intermediários para você. (apenas adicionar -r não funcionará; não tem efeito a menos que a fonte seja um diretório).

Você pode tentar a opção -r do GNU ln ("criar links relativos") e criar você mesmo os diretórios intermediários com mkdir -p {dirname} . Exemplo:

# usage mklinks from to [opts/predicates for find ..]
mklinks(){
    from=$1; shift
    to=$1; shift
    find "$from" -type f "$@" -print0 | from=$from to=$to gxargs -0 sh -c '
        for a; do
            t="$to/${a#$from}"; b=${t##*/}
            mkdir -vp "${t%$b}" && gln -vrs "$a" "$t"
        done
    ' sh
}

mklinks ../../1/a . \! -name '*data*'

Claro, se você estiver no Linux, altere gxargs para xargs e gln para ln .

    
por 04.10.2018 / 18:30