Como encontro links simbólicos onde o caminho de destino corresponde a um padrão?

4

Estou tentando encontrar todos os links simbólicos abaixo da pasta atual cujo destino contém 'Dropbox'

Meu palpite foi:

find . -type l -iname '*Dropbox*'

Mas isso não retorna nada.

Eu quero encontrar itens como:

com.adobe.illustrator.plist -> /Volumes/data/Dropbox (Personal)/Mackup/Library/Preferences/com.adobe.illustrator.plist
com.apple.Terminal.plist -> /Volumes/data/Dropbox (Personal)/Mackup/Library/Preferences/com.apple.Terminal.plist
com.noodlesoft.Hazel.plist -> /Volumes/data/Dropbox (Personal)/Mackup/Library/Preferences/com.noodlesoft.Hazel.plist

para que eu possa recriar os links sem o texto (Personal) . (Se há uma maneira de fazer isso com uma linha, isso seria excelente!)

    
por Ze'ev 16.11.2017 / 12:58

1 resposta

5

Se o seu find suportar -lname ou -ilname (extensões GNU também suportadas por alguns BSDs (incluindo macOS que seu /Volumes sugere que você esteja usando)).

find . -lname '*Dropbox*' -exec ls -ld {} +

Ou não insensível a maiúsculas e minúsculas:

find . -ilname '*dropbox*' -exec ls -ld {} +

Se não (ou mesmo se sim, se você quiser fazer qualquer coisa facilmente com esses links ou preferir uma lista ordenada) e tiver zsh (fornecido por padrão no macOS), você poderia fazer:

zmodload zsh/stat
set -o extendedglob # for (#i) for case insensitive
link_match() {
  local target
  zstat -A target +link -- "${2-$REPLY}" &&
    [[ $target = $~1 ]]
}
ls -ld -- **/*(D@e:'link_match "(#i)*dropbox*"':)

Ou para recriar os links:

zmodload zsh/stat
for l (**/*(D@))
  zstat -A target +link -- $l &&
    [[ $target = *"Dropbox (Personal)"* ]] &&
    rm -f -- $l &&
    ln -s -- ${target//" (Personal)"} $l

Note que qualquer código shell sempre pode ser escrito em uma linha, se necessário, mas não vejo o ponto. Aqui, junte essas linhas se quiser em uma linha.

Para fazer algo semelhante com utilitários bash e GNU ou FreeBSD / macOS, é mais complicado e menos eficiente:

LC_ALL=C find . -lname '*Dropbox (Personal)*' -exec bash -c '
  for l do
    target=$(readlink "$l" && echo .) || continue
    target=${target%??}
    rm -f "$l" &&
      ln -s -- "${target//" (Personal)"}" "$l"
  done' bash {} +
    
por 16.11.2017 / 13:15

Tags