Usando uma função zsh no find?

1

Estou no OS X e defini uma função chamada finderpackage que tenta determinar se uma pasta é, na verdade, um "pacote" (também, erroneamente, conhecido como "pacote"), de acordo com o Finder.

Meu uso pretendido para isso era limitar find de descer para essas pastas, o que às vezes é útil.

Um aplicativo seria encontrar o tamanho dos arquivos em uma subárvore enquanto tratava aplicativos, estruturas, formatos de documentos que são realmente pastas e similares como "arquivos" únicos, assim como o Finder faria:

find . -xdev \( -exec finderpackage {} \; -exec du -sk {} \; -prune \) -or \( -type f -exec du -k {} \; \)

No entanto, este exemplo não funciona, pois find reclama: find: finderpackage: No such file or directory

Não posso usar uma função zsh dessa maneira?

(Claro que posso reescrevê-lo como um script, estou curioso para saber se eu perdi alguma coisa sobre como as funções são usadas?)

    
por PaulRein 21.05.2014 / 11:22

1 resposta

3

funções são características da linguagem shell. /bin/zsh é um comando que é um interpretador da linguagem zsh . find é outro comando destinado a encontrar arquivos. Com -exec , ele pode executar um comando. Uma função zsh não é um comando.

find precisaria ter zsh interpretando o código na função. Para isso, seria necessário invocar zsh de uma maneira que informa para carregar o código dessa função e executá-lo com o arquivo encontrado. Isso pode ser feito com:

find ... -exec zsh -c "(){$functions[finderpackage];}"' "$@"' zsh {} \; ...

(acima, estamos chamando zsh com um script embutido (com -c ) cujo conteúdo usa uma função anônima ( (){code} args ) onde o código é copiado do da função finderpackage no shell que chama esse comando find ).

Mas isso significa invocar um comando zsh por arquivo que será terrivelmente ineficiente.

zsh globbing tem recursos e qualificadores recursivos que o tornam quase equivalente a find , mas, infelizmente, uma coisa que falta é a capacidade de controlar como a travessia do diretório é feita de maneira arbitrária.

Você pode remover diretórios com base no nome deles, como:

setopt extendedglob
print -rl -- (^*.pkg/)#*(.)

Para remover os diretórios *.pkg . Mas você não pode remover diretórios antigos ou conter este ou aquele arquivo, por exemplo. Para isso, você teria que recorrer à passagem manual do diretório.

Uma coisa que você pode fazer, embora não seja muito eficiente, é interagir com find como coproc e usar seu -ok :

coproc stdbuf -o0 find . -type f -exec printf 'f:%s
find ... -exec zsh -c "(){$functions[finderpackage];}"' "$@"' zsh {} \; ...
' {} \; -o \ -type d -exec printf 'd:%s
setopt extendedglob
print -rl -- (^*.pkg/)#*(.)
' {} \; -ok true \; -prune 2> /dev/null while IFS=: read -rpd '' type file; do case $type in (d) if finderpackage $file; then print -p y du -sk $file else print -p n fi;; (f) du -k $file esac done
    
por 21.05.2014 / 11:35

Tags