ln -s $ SOURCE / * exceto - com find?

1

Eu quero fazer um link simbólico de todos os diretórios e arquivos no primeiro nó de $SOURCE to $HOME/Destination/ . Pseudocódigo

ln -s $SOURCE/* exceptThese $HOME/Destination/

Proposta

find $HOME ! -name Data -o -name Labs -exec \
   ln -s "$0" $HOME/Documents/

onde não tenho certeza sobre $0 .

Como você pode ligar tudo, exceto no primeiro nó?

    
por Léo Léopold Hertz 준영 01.06.2016 / 23:51

3 respostas

2

Se você quiser criar links simbólicos de $HOME/this , $HOME/there/that , $HOME/Data/ddd etc., mas não $HOME/Data ou $HOME/somewhere/Labs , os critérios de correspondência devem ser

find "$HOME" ! \( -name Data -o -name Labs \) -exec …

Você estava com parênteses faltando. A justaposição liga-se mais do que -o , então -name Data -o name Labs -exec … executa o comando para arquivos denominados Labs apenas (exceto para arquivos denominados Data , mas nenhum deles também pode receber o nome Labs ).

Se você quis excluir todos os arquivos em Data e Labs , precisará da ação -prune , que diz a find para ignorar completamente os diretórios, sem percorrê-los recursivamente.

find "$HOME" \( -name Data -o -name Labs \) -prune -o -exec …

Isso exclui qualquer subárvore cuja raiz seja chamada Data , não apenas $HOME/Data . Se você quiser excluir apenas $HOME/Data , mas não, por exemplo, $HOME/sub/data , você pode usar -path (se sua implementação find for compatível).

find "$HOME" \( -path "$HOME/Data" -o -path "$HOME/Labs" \) -prune -o -exec …

Agora, para a parte -exec . Em uma ação -exec , use {} (em um argumento próprio) para representar o caminho que find encontrou. Coloque um ; (citado para que seja passado para find e não seja analisado pelo shell) no final do comando para ser executado.

find … -exec ln -s {} "$HOME/Documents/" \;

Se você apenas deseja os arquivos diretamente em $HOME e não os arquivos em subdiretórios, então find não é a melhor ferramenta para o trabalho: ele foi projetado para navegação recursiva. Use um loop de shell. Observe que o padrão * ignora os arquivos de ponto, ou seja, todos os arquivos cujo nome começa com . e o padrão .* corresponde a todos os arquivos de pontos mais . e .. , esses dois devem ser ignorados explicitamente.

for x in ~/* ~/.*; do
  case "${x##*/}" in
    .|..|Data|Labs) continue;; # Skip those entries
  esac
  ln -s "$x" "$HOME/Documents";;
done
    
por 02.06.2016 / 01:38
1

No Bash, você pode ativar a opção extglob:

$ shopt -s extglob                                #Enables extglob
$ ls -l "$HOME"/!(Data|Labs|Documents)            #Test run
$ ln -s "$HOME"/!(Data|Labs|Documents) \
        "$HOME"/Documents/                        #Create symlinks
$ shopt -s extglob                                #Disable extglob

Editar: usando a pesquisa de acordo com sua postagem original, isso deve funcionar:

$ find "$HOME" \
    -mindepth 1 \
    -maxdepth 1 \
    ! -name Data ! -name Labs ! -name Documents\
    -exec ln -s {} "$HOME"/Documents/ \;

A opção mindepth exclui o diretório raiz. A opção maxdepth exclui subdiretórios. Cada ! -name exclui um caminho. O {} argumento para -exec é o que você estava procurando em vez de $0 .

    
por 02.06.2016 / 01:09
-1

Para fazer o link para tudo find encontra outro que não o primeiro resultado, você pode fazer isso:

for item in "$(find "$HOME" ! -name Data -o -name Labs | tail --lines=+2)"; do
    ln -s "$item" "$HOME"/Documents/
done
    
por 02.06.2016 / 00:07

Tags