Em Zsh,
- para copiar arquivos normais, posso usar
cp source-dir/*(.) dest-dir/
- para copiar diretórios:
cp source-dir/*(/) dest-dir/
- para copiar todo o resto, por exemplo, links simbólicos, pipes e dispositivos:
cp source-dir/*(^./) dest-dir/
Mas como é possível copiar, por exemplo, links simbólicos para arquivos normais, mas não para diretórios de links simbólicos? Ou vice-versa, links simbólicos para diretórios, mas não links simbólicos para arquivos normais?
Use o
-
qualificador para os seguintes qualificadores para aplicar após a resolução do link simbólico, combinado com@
(antes do-
!) para testar links simbólicos.De
info zsh qualifiers
(o mesmo online para a versão mais recente do zsh):Lembre-se de que se você ativar a conclusão (com
compinit
), poderá obter ajuda on-line sobre os qualificadores pressionando Tabcomo de costume, onde verá:Também pode ser interessante notar que por resolução de link simbólico aqui, queremos dizer resolução completa de link simbólico. Por exemplo,
*(@-.)
também selecionará um arquivo que seja um link simbólico para outro arquivo que seja um link simbólico para um arquivo normal (como com GNUfind
ou-xtype f
com[
's-f
). Como visto acima,*(@-@)
, o mesmo que-@
não é para links simbólicos para links simbólicos, mas para links simbólicos quebrados (iguais aos do GNUfind
)-xtype l
, ou seja, arquivos que após a resolução completa do link simbólico não podem ser determinados como sendo outra coisa senão um link simbólico².Para verificar apenas o tipo de alvo direto de um link simbólico, seria mais complicado, pois você precisaria fazer um nível de resolução de link simbólico manualmente³.
Poderia ser algo como:
Onde você usaria
*(@e[target_of_type X])
para selecionar links simbólicos cujo alvo direto é do tipoX
, ondeX
aqui é baseado no primeiro caractere das
representação tring domode
(o mesmo que no primeiro campo da saída dels -l
), portanto-
, para regular,d
para diretório,l
para link simbólico etc:¹ Estritamente falando, deveria ser "qualquer link simbólico para o qual a chamada do sistema 'stat' falha" , embora isso possa ter sido menos claro para leitores casuais. Isso
-
alterna de usarlstat()
para usarstat()
no mesmo arquivo, mas sestat()
falhar, os qualificadores serão aplicados com base no resultadolstat()
. É por isso que-@
seleciona links simbólicos quebrados, mas também pode causar confusão, como por exemplo,*(-L+0)
, destinado a retornar arquivos não vazios após a resolução do link simbólico, também retornaria links simbólicos quebrados cujo comprimento de destino é maior que 0, portanto, qualquer link simbólico quebrado, uma vez que um destino de link simbólico não pode seja uma string vazia. De qualquer forma,*(-.L+0)
provavelmente seria mais apropriado nesse caso, independentemente dessa questão.² Por exemplo, porque a cadeia de links inclui um para um arquivo que não existe ou atravessa um diretório para o qual você não tem permissão de pesquisa ou há um loop de link simbólico...
³ Em vez de deixar o sistema fazer essa resolução. Em sistemas baseados em Linux, no caso dos links simbólicos mágicos em
/proc/*/fd
, fazer essa resolução manualmente pode produzir o resultado errado, pois o caminho de destino anunciado desses links simbólicos (conforme retornado pelareadlink()
chamada do sistema) não se refere necessariamente ao arquivo aberto no correspondentefd
. Esse é o caso principalmente quando o arquivo foi excluído, ondereadlink()
retorna o caminho original(deleted)
anexado a ele, enquanto umstat()
on consegue retornar informações do arquivo excluído.Como isso não é uma propriedade do link simbólico, mas do alvo do link simbólico, não há globo para fazer isso.
Então, você terá que escrever um
for
loop sobre todos os links simbólicos (for symlink in source-dir/*(@); do…
), e nele, terá que usarreadlink "${symlink}"
para obter o alvo do link simbólico individual e, em seguida, verificar[[ … ]]
se o link simbólico aponta para um diretório ([[ -d…
) e caso contrário (||
)continue
para o próximo link simbólico.