Como tornar o script zsh personalizado executável automaticamente?

2

Eu devo estar perdendo algo incrivelmente simples sobre como fazer isso, mas eu tenho um script simples:

extract () {
  if [ -f $1 ] ; then
    case $1 in
      *.tar.bz2)   tar xvjf $1    ;;
      *.tar.gz)    tar xvzf $1    ;;
      *.tar.xz)    tar xvJf $1    ;;
      *.bz2)       bunzip2 $1     ;;
      *.rar)       unrar x $1     ;;
      *.gz)        gunzip $1      ;;
      *.tar)       tar xvf $1     ;;
      *.tbz2)      tar xvjf $1    ;;
      *.tgz)       tar xvzf $1    ;;
      *.zip)       unzip $1       ;;
      *.Z)         uncompress $1  ;;
      *.7z)        7z x $1        ;;
      *.xz)        unxz $1        ;;
      *.exe)       cabextract $1  ;;
      *)           echo "\'$1': unrecognized file compression" ;;
    esac
  else
    echo "\'$1' is not a valid file"
  fi
}

O script funciona, mas não consigo fazer com que ele seja executável por padrão quando efetuo login.

Eu consultei esta resposta muito completa: Como definir e carregar sua própria função shell em zsh , e eu consegui fazer com que meu $ fpath mostre o diretório apropriado onde eu armazenei a função.

No meu perfil .zshrc, adicionei fpath=( ~/.local/bin "${fpath[@]}" ) ao final, que é o caminho onde minhas funções vivem.

Quando eu insiro echo $fpath , recebo:

/home/me/.local/bin /home/me/.oh-my-zsh/plugins/git /home/me/.oh-my-zsh/functions /home/me/.oh-my-zsh/completions ...

No entanto, ele não funciona a menos que eu digite explicitamente autoload -Uz extract cada vez que eu fizer login.

Existe uma maneira de fazer o diretório inteiro ser carregado automaticamente quando eu fizer login?

    
por Ryan Ward 09.03.2018 / 07:06

2 respostas

5

Você está misturando scripts e funções.

Criando um script

Um script é um programa independente. Pode acontecer de ser escrito em zsh, mas você pode invocá-lo de qualquer lugar, não apenas de uma linha de comando zsh. Se acontecer de você executar um script escrito em zsh a partir de uma linha de comando zsh ou outro script zsh, isso é uma coincidência que não afeta o comportamento do script. O script é executado em seu próprio processo, não influencia seu pai (por exemplo, ele não pode alterar variáveis ou o diretório atual).

Seu código realiza uma tarefa independente que pode ser invocada de qualquer lugar e não precisa acessar o estado do shell que o executa, portanto, ele deve ser um script, não uma função.

Um script deve ser um arquivo executável: chmod +x /path/to/script . Ele deve começar com uma linha shebang para permitir que o kernel saiba qual programa usar para interpretar o script. No seu caso, adicione esta linha ao topo do arquivo:

#!/usr/bin/env zsh

Coloque o arquivo em um diretório listado na variável $PATH . Muitos sistemas configuram ~/bin ou ~/.local/bin no padrão PATH de um usuário, para que você possa usá-los. Se você quiser adicionar outro diretório, consulte link

Quando você digita um nome de comando que não é um alias, uma função ou um incorporado, o shell procura por um arquivo executável com esse nome em $PATH e o executa. Assim, você não precisa declarar o script para o shell, basta soltá-lo no lugar certo.

Fazendo uma função

Uma função é um código que é executado dentro de uma instância de shell existente. Ele tem acesso total a todo o estado do shell: variáveis, diretório atual, funções, histórico de comandos, etc. Você só pode invocar uma função em um shell compatível.

Seu código pode funcionar como uma função, mas você não ganha nada fazendo isso funcionar e perde a capacidade de invocá-lo de outro lugar (por exemplo, de um gerenciador de arquivos).

No zsh, você pode disponibilizar uma função para sessões interativas, incluindo sua definição em ~/.zshrc . Como alternativa, para evitar a sobrecarga de .zshrc com um número muito grande de funções, você pode usar o mecanismo de carregamento automático. O carregamento automático funciona em duas etapas:

  1. Declare o nome da função com autoload -U myfunction .
  2. Quando myfunction é invocado pela primeira vez, zsh procura um arquivo chamado myfunction nos diretórios listados em $fpath e usa o primeiro arquivo que encontra como a definição de myfunction .

Todas as funções precisam ser definidas antes do uso. É por isso que não é suficiente colocar o arquivo em $fpath . Declarar a função com autoload na verdade cria uma definição de stub que diz "carregue essa função de $fpath e tente novamente":

% autoload -U myfunction
% which myfunction
myfunction () {
        # undefined
        builtin autoload -XU
}

O Zsh tem um mecanismo para gerar esses stubs explorando $fpath . Está incorporado no subsistema de conclusão.

  • Coloque #autoload como a primeira linha do arquivo.
  • No seu .zshrc , certifique-se de ter definido totalmente fpath antes de chamar a função de inicialização do sistema de conclusão compinit .

Note que o arquivo contendo uma definição de função deve conter a função corpo , não a definição da função, porque o que o zsh executa quando a função é chamada é o conteúdo do arquivo. Então, se você quisesse colocar seu código em uma função, você o colocaria em um arquivo chamado extract que está em um dos diretórios em $fpath , contendo

#autoload
if [ -f $1 ]; then
…

Se você deseja ter o código de inicialização que é executado quando a função é carregada, ou para definir funções auxiliares, você pode usar este idioma (usado na distribuição zsh). Coloque a definição da função no arquivo, além de todas as definições auxiliares e qualquer outro código de inicialização. No final, chame a função, passando os argumentos. Então myfunction conteria:

#autoload
my_auxiliary_function () {
  …
}
myfunction () {
  …
}
myfunction "$@"

P.S.

7z x funciona na maioria dos tipos de arquivo.

    
por 09.03.2018 / 12:59
1

Existem várias possibilidades para corrigir este problema:

  • você pode colocar essa função no seu .zshrc;
  • você pode criar seu script;
  • você pode colocar o código da sua função diretamente em um arquivo chamado extrair em um diretório que esteja no seu PATH.
por 09.03.2018 / 08:46