2 pontos por GN⁺ 2024-06-24 | 2 comentários | Compartilhar no WhatsApp
  • Quando usuários Unix colocam scripts pessoais em ~/bin/ e os adicionam ao PATH, nomes curtos de comandos podem entrar em conflito com novos comandos do sistema
  • Em ambientes com muitos comandos fornecidos, como Debian/Ubuntu, o risco aumenta; no notebook Ubuntu do exemplo, foram contabilizados 21.733 comandos em /usr/bin
  • Colocar uma vírgula (,) antes dos comandos pessoais faz com que o shell e as ferramentas a tratem como um caractere comum de nome de arquivo, ao mesmo tempo em que a distingue facilmente dos comandos do sistema
  • A vírgula pode ser digitada sem Shift e tem menos chance de causar conflitos do que parênteses, barra invertida, dois-pontos, crase, apóstrofo, barra e ponto, que têm significados fortes no shell
  • Ao pressionar Tab depois de ,, é possível percorrer imediatamente a lista de comandos pessoais, facilitando manter os nomes dos comandos em ~/bin/ bem organizados

Por que nomes de comandos pessoais entram em conflito

  • Muitos usuários Unix criam ~/bin/ no diretório home e o adicionam ao PATH para usar comandos utilitários pessoais e scripts de shell
  • O problema é que os nomes dos scripts pessoais costumam ser combinações curtas de letras minúsculas, o que os torna fáceis de se parecerem com comandos básicos do sistema
  • Quando uma distribuição Linux adiciona um novo comando, ele pode acabar tendo por acaso o mesmo nome de um comando pessoal existente
  • Em ambientes da família Debian, o grande número de comandos fornecidos torna esse problema mais realista
    • No notebook Ubuntu do exemplo, contar os comandos diretamente sob /usr/bin resulta em 21.733
    • apt-file search -x '^/usr/bin/[^/]*$' | wc -l

Vantagens do prefixo com vírgula

  • A solução é mudar os nomes dos comandos pessoais para uma forma que seja fácil de digitar, mas improvável de ser escolhida como nome de comando do sistema
  • O critério de conveniência de digitação é não usar a tecla Shift, e não há muitos caracteres seguros que satisfaçam essa condição
    • Letras minúsculas já são usadas com frequência em comandos do sistema
    • Parênteses, barra invertida, dois-pontos, crase e apóstrofo têm significados especiais no shell
    • A barra é separador de diretórios, portanto não pode fazer parte de um nome de arquivo
    • O ponto, no início de um nome de arquivo, indica arquivo oculto; em outras posições, também é usado com frequência para separar extensões
  • A opção que sobra é a simples vírgula (,), e as ferramentas ao redor e o shell tratam a vírgula como um caractere comum dentro do nome de arquivo
  • Ao adicionar a vírgula como prefixo a cada comando pessoal, eles ficam claramente separados dos comandos do sistema, facilitando evitar colisões de nome
  • Usada com autocompletar por Tab, permite ver imediatamente a lista de comandos pessoais depois de digitar ,
    • A lista de exemplo inclui ,complete-scp, ,complete-ssh, ,coreoff, ,coreon, ,find, ,go-thpgp, ,gr, ,hss, ,mount-thpgp, ,mount-twt, ,range, ,svn-store-password, ,umount, entre outros
  • Essa abordagem vem sendo usada há cerca de 10 anos e é recomendada como uma forma de manter bem organizados os nomes de comandos pessoais em ~/bin/

2 comentários

 
GN⁺ 2024-06-24
Comentários no Hacker News
  • Só pelo título, achei que seria uma ideia horrível, mas na prática gostei bastante. Gostei especialmente da parte de listar todas as minhas ferramentas com Tab
    Ultimamente não tenho sofrido muito com colisões de namespace, e também é verdade que, depois que migrei para gestão, meu senso técnico ficou meio enferrujado. Meu stack técnico parece estar uns 10 anos defasado, e fico me perguntando por onde seria bom começar para voltar a acompanhar o que há de mais atual

    • O jeito legal hoje em dia parece ser criar algo por conta própria no tempo livre e aprender naturalmente durante o processo. Autossuficiência, criatividade e iniciativa própria são a pegada atual; quanto mais você constrói, mais pega o jeito de resolver problemas reais e mais motivação tem para descobrir soluções modernas por conta própria
    • Também estou na área de gestão e sinto que, se eu não continuar acompanhando, minhas habilidades técnicas vão atrofiar
      O que eu faço é criar ferramentas que facilitem minha própria vida. Por exemplo, se há um serviço web na empresa que eu uso com frequência para consultas simples, procuro ver se existe uma API e escrevo uma CLI para acelerar as tarefas do dia a dia. Depois de deixá-la do jeito que gosto, compartilho com a equipe, mas é difícil convencer outras pessoas a experimentarem. Ainda assim, como eu uso todos os dias, não me preocupo muito com isso
    • Pelo mesmo motivo, criei um projeto paralelo com um stack separado e mais em alta, em vez do stack com que já estava acostumado no trabalho
      O objetivo era enxergar novas perspectivas e conseguir conversar sobre tendências, e parte disso agora acabou chegando ao trabalho. Isso também me ajudou a entender melhor os componentes mais antigos
  • Não entendo muito bem esse problema. Basta colocar meu diretório bin no começo do $PATH, não no fim. Para ver meus comandos, simplesmente rodo ls ~/bin

    • Aí alguma ferramenta pode esperar que $0 esteja em um caminho do sistema, isso quebrar, e começar uma depuração frustrante
      No fim, é uma questão de escolher qual veneno tomar
    • Não bastaria lembrar os nomes que eu dei? Não entendo por que isso é visto como uma espécie de hack
    • Uma das vantagens é poder usar a autocompletação do fzf. Por exemplo, no fish, dá para digitar a primeira letra de um comando e apertar Tab para abrir o fzf
      Assim, só com ,+Tab você consegue filtrar rapidamente os comandos personalizados. Já ls ~/bin exige digitar bastante para algo feito com frequência; ou então talvez seja preciso procurar primeiro no histórico/autocompletação com ls+seta para cima várias vezes
    • ls ~/bin é muito mais lento de digitar do que ,
  • Eu uso nomes curtos de comandos personalizados, como aa, st, di, dp, cm, le, para wrappers finos em torno do git
    Um deles realmente entra em conflito com um utilitário instalado por padrão em algum sistema. Mesmo assim, como meu diretório bin vem antes dos diretórios do sistema no $PATH, o meu ganha, e não tenho muito interesse nessa ferramenta conflitante. Se alguma outra ferramenta útil para mim conflitasse com a minha, eu provavelmente criaria para essa outra ferramenta um alias que não conflitasse, em vez de renomear a minha. Essas ferramentas de duas letras são convenientes demais

    • Esse tipo de abordagem pode levar a problemas como apt-get upgrade executar Dwarf Fortress
      https://askubuntu.com/questions/938606/dwarf-fortress-starti...
    • Exato. Nomes de 1 a 3 letras deveriam ficar reservados para aliases, funções e scripts do usuário, além de utilitários padrão
    • Meus aliases de git geralmente são combinações de duas letras começando com g. Por exemplo, gs é git status
      Só que às vezes eu realmente preciso do GhostScript. Ele é excelente para casos como incorporar fontes em arquivos PDF. Normalmente, nessas horas, uso env gs
    • Meus comandos pessoais começam todos com j. Quando java apareceu, isso ficou bem divertido. Usar vírgula é uma ideia bem interessante
      Ainda bem que não comecei com k, por causa do KDE :)
    • É uma opinião um tanto forte, mas acho que comandos do sistema não deveriam ser tão facilmente acessíveis quanto comandos do usuário. Deveria existir algum tipo de namespace
      Por exemplo, acho que mkfs deveria ser chamado como sys::mkfs. A linha que separa comandos do sistema e comandos do usuário pode ser definida de várias maneiras, e haverá partes ambíguas, mas se o usuário pode executar por engano um comando que nem sabe que existe e que nunca instalou explicitamente, então esse comando não deveria ficar exposto diretamente no namespace global
  • Há uma pergunta relacionada
    Eu uso Windows na maior parte do tempo e, como o autor, criei vários scripts de CLI centrados em Python e os coloco no equivalente a ~/bin/. Se eu definir python.exe como o programa padrão para a extensão .py e adicionar .py ao %pathext%, consigo executar ~/bin/hello.py digitando apenas hello de qualquer diretório, e uso isso centenas de vezes por dia. Hoje em dia uso mais Linux, mas ainda sou iniciante e não consegui fazer do mesmo jeito. No Linux parece não existir o conceito de “programa associado”, então não dá para simplesmente chamar um arquivo .py e fazer o shell executá-lo com Python. Claro, posso dar chmod +x no script, mas aí preciso colocar um shebang no próprio script, o que me incomoda por parecer hardcoded. E se no futuro eu quiser executar scripts .py com /usr/bin/nohtyp em vez de /usr/bin/python? Além disso, também não encontrei uma forma de omitir a parte .py ao chamar o script. Não quero criticar o design do Linux, e sei que ele tem muitas vantagens, mas eu realmente quero executar hello.py que está no $PATH como hello

    • No Linux, ainda acho que o shebang é a ferramenta certa para esse problema. Para algo simples, coloque um link simbólico my_python em algum diretório do caminho e use o shebang /usr/bin/env my_python
      Se quiser uma abordagem mais principiada, veja a ferramenta update-alternatives. Ela oferece esse tipo de abstração de forma mais geral: https://linuxconfig.org/how-to-set-default-programs-using-up...
    • Outras pessoas já deram a solução, mas quero acrescentar um ponto sobre o porquê
      No Linux — na verdade, na maioria das plataformas fora o Windows — o significado das extensões de arquivo é muito mais fraco. Para qualquer tipo de executável, o que determina se ele pode ser executado não é a extensão, e sim coisas como a flag +x. Isso permite reescrever algo em outra linguagem de implementação sem quebrar quem chama. A extensão .py só faz sentido para módulos importados e usados; se for um script executável, quando necessário você olha o shebang. Scripts distribuídos externamente normalmente usam #!/usr/bin/env python, e scripts incluídos em pacotes da distribuição acabam sendo sobrescritos com algo como #!/usr/bin/python. Além disso, o shebang não dá suporte a vários argumentos, mas o env do GNU oferece a opção -S, que consegue simular isso. Ainda resta, porém, o problema do tamanho dos argumentos
    • Basta remover .py do nome do arquivo. Chamá-lo de "hello" é perfeitamente aceitável
      Não consigo pensar em grandes desvantagens do shebang. Se você realmente quiser executar com outro interpretador, explicite como "nohtyp hello". Se ainda assim isso incomodar muito, você pode definir um alias no arquivo de inicialização do shell. Por exemplo, no bash dá para fazer alias hello="python3 /path/to/hello.py". Se quiser, também dá para escrever um script curto que gere automaticamente aliases desse tipo para o conteúdo de um diretório específico
    • Esse conceito existe, mas não dentro da sintaxe do shell. Normalmente é uma questão no nível da aplicação, delegada ao desktop/GUI
      Em scripts de shell, normalmente você adiciona um shebang e torna o arquivo executável, declarando o executável no próprio script. Pense no shebang como uma espécie de extensão de arquivo. Se ./malware.py não funcionar depois de chmod +x ./malware.py, verifique o caminho apontado pelo shebang. Se o interpretador consegue executar o script como um argumento comum, dá para obter um comportamento parecido com algo como xdg-open malware.py. Seria equivalente a dar duplo clique no gerenciador de arquivos padrão. Quando eu usava Linux como sistema operacional principal no desktop, tive um alias chamado xop, mas só o usava para arquivos de dados, como imagens ou documentos, cujo comportamento padrão já estava correto. Não recomendo definir o programa padrão de scripts executáveis como o interpretador. Por padrão, talvez você queira abrir scripts em um editor, e não executá-los. Acho que xdg-open é uma ferramenta do lado do Gnome, mas isso não quer dizer que não possa ser usada em outros desktops; eu também a usava no Xubuntu. Se você realmente quiser executar por padrão todos os arquivos Python também no contexto da GUI, dá para configurar esse padrão, mas man xdg-open pode ajudar. Reforçando: não é um bom conselho
    • Isso não atinge diretamente o objetivo, mas o shebang é apenas meio hardcoded. A forma “correta” de usar shebang, ainda que com alguns cuidados — veja https://unix.stackexchange.com/a/29620 — é #!/usr/bin/env python
      Assim, o primeiro python encontrado no caminho será executado. Se no futuro você quiser executar com /usr/bin/nohtyp em vez de /usr/bin/python, pode criar um link simbólico chamado python apontando para /usr/bin/nohtyp em um diretório pesquisado antes de /usr/bin. Por exemplo, adicione ~/myCommandPreferences ao início do $PATH
  • Outra forma de evitar conflitos no $PATH é criar nomes de executáveis bem longos, com pouca chance de serem usados por outros executáveis, e colocar aliases curtos no bashrc
    Aliases não afetam executáveis chamados dentro de scripts, e nos meus scripts eu posso continuar referenciando os nomes longos. A desvantagem é que você não obtém o mesmo nível de usabilidade com autocompletar por Tab, embora essa parte seja realmente muito boa. Além disso, ainda pode haver conflitos em scripts que precisam ser executados com source, e não como subprocessos, como o script de ativação de venv do Python, mas esses casos são raros

    • No zsh, esse autocompletar também funciona
  • Começar com vírgula é uma técnica comum também na comunidade de expansores de texto/substituição de texto

    • Sim. A maioria dos meus aliases do vim também começa com ,
  • Recentemente, ao dar uma olhada em ~/.local/bin/, descobri dezenas de executáveis que não me lembrava de ter colocado ali
    A maioria era relacionada ao pyside, mas havia outros scripts também. Tive que abrir um por um para lembrar quais scripts eu mesmo tinha escrito e quais tinham sido criados por outras pessoas. Se os nomes dos meus scripts começassem com vírgula, teria sido muito mais rápido, e isso também teria ajudado a lembrar, antes de abrir cada script, por que eu o tinha criado

    • Normalmente ~/.local/bin/ é para scripts instalados, e o que você escreve localmente fica em ~/bin/
  • Passo. Basta colocar meu bin pessoal antes no $PATH e usar /usr/bin ou /bin quando precisar referenciar programas encobertos
    A lista de ferramentas personalizadas pode ser exibida com ~/bin/[Tab]

    • Não quero apontar utilitários do sistema para os meus e ainda assim usar o mesmo nome, então não entendo a necessidade de continuar lembrando da vírgula
      Se eu não gosto do grep do sistema, por exemplo o grep do Solaris, e quero usar o GNU grep que prefiro, por que simplesmente não deixá-lo como grep?
  • Ter encontrado essa ideia há 5 anos me ajudou a colocar ordem no meu conjunto de truques de shell. Entre aliases e ~/bin, tenho mais de 50 comandos com vírgula, e minha vida no shell ficou muito mais fluida do que naquela bagunça de antes

  • Também foi discutido em 2020: https://news.ycombinator.com/item?id=22778988 (90 comentários)

 
kayws426 2024-06-24

Que tal usar '_'?