24 pontos por GN⁺ 2025-10-23 | 2 comentários | Compartilhar no WhatsApp
  • Apresenta, entre vários scripts shell criados ao longo de mais de 10 anos mantendo dotfiles, os que são usados com mais frequência
  • Divide-os em área de transferência, gerenciamento de arquivos, internet, processamento de texto, launcher de REPL, data/hora, AV, processos, referência rápida, sistema e miscelânea, e mostra cada script como um wrapper curto com foco em exemplos práticos
  • A maioria dos scripts funciona em macOS e Linux, e a filosofia central é “alisar as pequenas chatices incômodas das ferramentas que já existem”
    • Integra utilitários padrão como pbcopy/xclip, python3 -m http.server, yt-dlp, ffmpeg, mpv etc.
  • Entre os mais usados estão copy/pasta/pastas/cpwd, mkcd/tempe/trash/mksh, serveit/getsong/getpod/getsubs, scratch/straightquote/markdownquote, timer/boop/tunes etc.

Apresentando os scripts que mais uso, criados enquanto mantinha meus dotfiles

  • Ao longo de mais de 10 anos gerenciando dotfiles pessoais, o autor organizou por área vários scripts shell que criou e usa com frequência
  • Cada script vem com objetivo, frequência de uso e exemplos representativos, aumentando a possibilidade de aplicação imediata
  • Os objetivos em comum são encurtar tarefas repetitivas, abstrair diferenças entre plataformas e melhorar segurança e legibilidade

Scripts relacionados à área de transferência

  • copy e pasta: wrappers para o gerenciador de área de transferência do sistema, baseados em pbcopy no macOS ou xclip no Linux
    • copy: copia a saída para a área de transferência
    • pasta: pega texto da área de transferência e imprime
    • Ex.: run_some_command | copy, pasta > file.txt, vim "$(pasta)", pasta | base64 --decode
  • pastas: ferramenta que imprime em tempo real cada novo conteúdo sempre que o estado da área de transferência muda
    • Útil para salvar todos os links copiados em um arquivo ou baixar vários links em lote
    • Ex.: pastas > everything_i_copied.txt, pastas | wget -i -
  • cpwd: copia o caminho do diretório atual para a área de transferência
    • Prático ao mudar de diretório entre várias abas de terminal

Scripts de gerenciamento de arquivos

  • mkcd foo: cria um diretório e entra nele imediatamente (atalho para mkdir foo && cd foo)
  • tempe: vai para um diretório temporário (cd "$(mktemp -d)"), sem necessidade de limpar depois ao fazer trabalho temporário em um ambiente sandbox
    • Ex.:
      # Download a file and extract it  
      tempe  
      wget 'https://example.com/big_file.tar.xz'  
      tar -xf big_file.tar.xz  
      # ...do something with the file...  
      
      # Write a quick throwaway script to try something out  
      tempe  
      vim foo.py  
      python3 foo.py  
      
  • trash: move arquivos para a lixeira (suporte a macOS/Linux), ajudando a evitar erros em comparação com rm puro
  • mksh: cria um novo arquivo de shell script, marca como executável e o abre imediatamente no editor

Scripts relacionados à internet

  • serveit: sobe um servidor local de arquivos estáticos a partir de um diretório local (porta padrão 8000, com alternativa se Python não estiver instalado)
  • getsong usa yt-dlp para baixar áudio na melhor qualidade disponível
  • getpod é um wrapper para obter o áudio de vídeos em formato adequado para podcast
  • getsubs extrai legendas em inglês com lógica de priorizar legendas oficiais e usar legendas automáticas como fallback. É adequado para pipelines de resumo e backup
  • wifi off/on/toggle: controla o Wi‑Fi do sistema, usado na resolução de problemas de rede
  • url: analisa uma string de URL e separa/extrai protocolo, hostname, caminho, query, hash etc.

Scripts de processamento de texto

  • line 10: imprime uma linha específica da entrada padrão (semelhante a head e tail)
  • scratch: serve para abrir rapidamente um buffer de texto temporário no Vim, como em $EDITOR $(mktemp), ideal para anotações descartáveis ou pequenas transformações
  • straightquote: converte aspas tipográficas em aspas normais, evitando problemas com aspas em código e reduzindo o tamanho de arquivos
  • markdownquote: adiciona > ao início de cada linha para gerar citações em Markdown
  • length: retorna o comprimento da string de entrada (pode substituir wc -c)
  • jsonformat: formata dados JSON de forma legível
  • uppered/lowered: converte strings para maiúsculas/minúsculas
  • nato bar: converte a string de entrada para o alfabeto fonético da OTAN (Bravo Alfa Romeo etc.)
  • u+ 2025: consulta o nome e o símbolo de um caractere Unicode
  • snippets foo: busca uma frase curta específica em um dicionário pessoal de snippets
    • snippet arrow retorna a seta →, e snippet recruiter retorna uma mensagem-modelo como “not interested”

Launchers de REPL

  • Inspirado no irb do Ruby, permite iniciar rapidamente REPLs de várias linguagens:
    • iclj: Clojure
    • ijs: Deno (ou Node, se Deno não estiver disponível)
    • iphp: PHP
    • ipy: Python
    • isql: SQLite (modo em memória no Bash)

Scripts de data e hora

  • hoy: imprime a data atual em formato ISO (ex.: 2020-04-20), útil como prefixo de nome de arquivo
  • timer 10m: temporizador (por exemplo, 10 minutos), com som e notificação do sistema ao terminar
  • rn: usa date e cal para mostrar a hora atual e o calendário mensal de forma mais agradável

Áudio, vídeo e processamento de imagem

  • ocr: extrai texto de arquivos de imagem no macOS (com expansão planejada)
  • boop: emite um alerta sonoro conforme sucesso/falha do comando anterior (uso intuitivo, por exemplo, após executar testes)
  • sfx: reproduz um arquivo de efeito sonoro específico (.ogg), integrado com boop e timer
  • tunes: reproduz arquivos de áudio com mpv (com suporte a shuffle)
  • pix: visualiza fotos com mpv
  • radio: launcher rápido para estações de rádio online favoritas
  • speak: remove Markdown do texto lido via stdin e o envia para síntese de voz (TTS)
  • shrinkvid: comprime arquivos de vídeo com ffmpeg
  • removeexif: remove dados EXIF de JPEGs, com suporte futuro planejado para mais formatos
  • tuivid: permite assistir a vídeos dentro do terminal; pouco usado na prática, mas uma função curiosa

Gerenciamento de processos

  • each: alternativa a xargs e find ... -exec, facilitando a execução de comandos complexos
  • running foo: procura processos em execução por palavra-chave específica (PID, comando etc.) e exibe o resultado em formato legível
  • murder: wrapper para kill, encerrando progressivamente do sinal mais suave ao mais forte. Ajuda a evitar erros ao solicitar o fechamento de programas
  • waitfor $PID: espera até que o PID especificado termine, mantendo-se acordado até lá
  • bb my_command: executa um comando em verdadeiro modo background, adequado para daemons e afins
  • prettypath: imprime $PATH com quebras de linha para facilitar a visualização de uma vez só (útil em depuração)
  • tryna my_command/trynafail my_command: repete até o comando ter sucesso (run until success) ou falhar (run until fail), útil em automações diversas como rede

Ferramentas de referência rápida

  • emoji: busca e imprime emojis por palavra-chave
  • httpstatus: imprime a lista completa de códigos de status HTTP e permite consultar a explicação de um código específico
  • alphabet: imprime todas as letras minúsculas e maiúsculas do alfabeto inglês (surpreendentemente útil com frequência)

Gerenciamento do sistema

  • theme 0/theme 1: altera o tema geral do sistema (escuro/claro), com integração a Vim, Tmux etc.
  • sleepybear: coloca o sistema em modo de suspensão (macOS, Linux)
  • ds-destroy: remove recursivamente arquivos .DS_Store, útil ao limpar pastas de usuários de macOS

Outros

  • catbin foo: exibe diretamente o código-fonte de um arquivo presente no PATH
  • notify: envia notificações no nível do sistema, útil para ser avisado assim que tarefas longas terminam
  • uuid: gera um UUID versão 4

Conclusão

  • Os scripts apresentados neste texto são ferramentas que o autor realmente usa com frequência
  • Scripts de atalho criados por conta própria são muito eficazes para ganho de eficiência no trabalho, prevenção de erros e aumento de produtividade
  • O autor recomenda que cada um também crie e use seus próprios scripts de automação

2 comentários

 
GN⁺ 2025-10-23
Comentários no Hacker News
  • O comando trash a.txt b.png move os arquivos a.txt e b.png para a lixeira, com suporte no Mac e no Linux. O jeito que eu fazia antes processava os arquivos um por um, então o som de exclusão tocava para cada arquivo e só dava para restaurar o último com ⌘Z no Finder. Dá para melhorar isso, mas, na prática, é mais conveniente usar o comando oficial trash já embutido no macOS. Como ele não usa o Finder, não há som nem restauração com ⌘Z, mas é mais rápido e ainda permite “Put Back”. E, para pretty-print de JSON, se usar jq em vez de node, dá para resolver com bem menos código, e hoje em dia o macOS já vem com jq pré-instalado. O mesmo vale para imprimir UUID: se você precisa de um UUID v4, o mais sensato é usar uuidgen (veja a man page)

    • Muitas vezes é melhor usar recursos embutidos do que scripts próprios. Por exemplo, no vim, em vez de usar markdownquote, basta selecionar a primeira coluna com ctrl-v, digitar "i> " e apertar escape. É mais curto e eficiente. Também fiquei curioso sobre por que u+ 2025 retorna ñ, já que o valor Unicode real é U+00F1. E catbin foo é o mesmo que cat "$(which foo)". Se você usa zsh, cat =foo é mais curto e mais poderoso. No zsh, há autocompletar depois do =, então dá para usar com segurança até em comandos longos. Eu uso muito coisas como file =firefox, vim =myscript.sh

    • Eu suponho que o autor não conhecia uuidgen. Gosto de como compartilhar esse tipo de conhecimento ou configuração sempre revela meus pontos cegos — é por isso que compartilhar é importante

    • O Python também consegue fazer pretty-print de JSON por padrão

      $ echo '{ "hello": "world" }' | python3 -m json.tool
      {
        "hello": "world"
      }
      
    • Valeu pela informação sobre trash. Até agora eu usava AppleScript no estilo tell app \"Finder\" to move {%s} to trash para mandar vários arquivos para a lixeira

    • Como alternativa a rm e trash, também recomendo o rip link do projeto rip

  • O ciclo de vida de um desenvolvedor é bem curioso. No começo, você usa só um ambiente de shell vanilla; com 1 ou 2 anos de carreira, cria centenas de linhas de scripts e aliases de bash; agora, com 15 anos de experiência, eu prefiro usar ao máximo só o shell padrão, sem aliases, e deixar as coisas complexas para Python ou Go

    • Essa tendência parece vir mais de preguiça do que de algum estado iluminado (e digo isso porque faço a mesma coisa). Graças aos colegas que gostam de mexer a fundo no ambiente, acabo conhecendo ferramentas novas com frequência, e recentemente até adicionei coisas como atuin e fzf no Linux

    • Eu coloco aliases e funções nos dotfiles para registrar/lembrar comandos usados com frequência. Vou atualizando minha coleção de ferramentas úteis e também fica fácil levar isso para uma nova workstation

    • Quando eu só tinha uma máquina nix, sentia mais vontade de customizar tudo. Agora, como uso várias máquinas ao mesmo tempo, prefiro só instalar os pacotes necessários e manter o ambiente uniforme

    • Coisas escritas em Python eu ainda chamo de script. Não acho que o termo script se limite apenas a shell script

    • Hoje em dia, trabalhando com engenheiros mais jovens e vendo como eles usam vários dotfiles, penso: “eu também fazia isso antigamente, era trabalhoso”. Agora seleciono as ferramentas com mais critério e personalizo só o necessário, com flexibilidade. E respeito o estilo dos outros também

  • Eu realmente gosto de encontrar esse tipo de post com dicas práticas no HN. Tenho curiosidade sobre como outros desenvolvedores realmente trabalham e o que eu posso aprender e aplicar. Mesmo quando penso de início “isso provavelmente não é para mim”, se alguma tarefa fica mais fácil, isso por si só cria um novo fluxo de trabalho. Então prefiro experimentar e ficar com o que funcionar. Também gostei do estilo do post original — o fato de indicar a frequência real de uso torna tudo muito mais prático. Muitas vezes eu resolvo tarefas simples abrindo as devtools do navegador e usando JavaScript. (Por exemplo, para converter uma string para minúsculas)

    • Seria interessante fazer uma análise real de custo-benefício, comparando o tempo do método do autor com o meu, incluindo o custo de criar/lembrar/consultar/migrar scripts

    • Esta imagem de cheatsheet de atalhos do Bash ajuda bastante

  • Em vez do script line, é mais simples imprimir uma linha específica com sed

    sed -n 2p file
    

    Isso imprime a segunda linha. Também dá para imprimir várias linhas com

    sed -n 2,4p file
    

    então acaba sendo mais vantajoso do que o script line

    • Eu costumo encadear vários comandos sed. Nesses casos, preciso ficar alterando o primeiro sed toda hora. Às vezes também preciso de um grep antes do sed, então quebrar em cat, tail e head deixa cada função mais modular e flexível. Isso combina com a filosofia Unix de fazer cada ferramenta cuidar de uma única coisa
  • Tenho alguns scripts simples que uso com frequência. Por exemplo:

    #!/usr/bin/env bash
    # ~/bin/,dehex
    
    echo "$1" | xxd -r -p
    
    #!/usr/bin/env bash
    # ~/bin/,ht
    
    highlight() {
      # Cores: 30=preto, 31=vermelho, 32=verde, ...
      escape=$(printf '\033')
      sed "s,$2,${escape}[$1m&${escape}[0m,g"
    }
    
    if [[ $# == 1 ]]; then
      highlight 31 $1
    elif [[ $# == 2 ]]; then
      highlight 31 $1 | highlight 32 $2
    elif [[ $# == 3 ]]; then
      highlight 31 $1 | highlight 32 $2 | highlight 35 $3
    elif [[ $# == 4 ]]; then
      highlight 31 $1 | highlight 32 $2 | highlight 35 $3 | highlight 36 $4
    fi
    

    Eu coloco , (vírgula) no começo dos scripts pessoais para alternar rapidamente para eles. Acho valioso gerar estatísticas periodicamente a partir do meu histórico sobre meus scripts pessoais e limpar os que já não uso mais

  • Ainda não consegui generalizar, mas tenho trabalhado de forma bem prática com um script unmv

    #!/bin/sh
    if test "$#" != 2
    then
      echo 'Error: unmv must have exactly 2 arguments'
      exit 1
    fi
    exec mv "$2" "$1"
    
  • Tem muitas dicas boas aqui, mas eu normalmente prefiro aprender e usar utilitários padrão (sed, awk, grep, xargs etc.). O motivo é que trabalho passando por vários sistemas, e meus scripts e aliases pessoais geralmente não estão instalados neles. Com utilitários padrão, dá para fazer quase tudo

    • Concordo totalmente. Você acaba usando só o padrão para conseguir trabalhar de qualquer lugar. Mas ferramentas realmente boas acabam virando instalação padrão ou ficando fáceis de instalar com apt-get. Acho mais desejável ter algo em forma de pacote bem mantido do que uma coleção de scripts pessoais
  • Vou compartilhar meu script favorito para extração de arquivos

    # ex - archive extractor
    # uso: ex <arquivo>
    function ex() {
      if [ -f $1 ] ; then
      case $1 in
        *.tar.bz2) tar xjf $1 ;;
        *.tar.gz) tar xzf $1 ;;
        *.tar.xz) tar xf $1 ;;
        *.bz2) bunzip2 $1 ;;
        *.rar) unrar x $1 ;;
        *.gz) gunzip $1 ;;
        *.tar) tar xf $1 ;;
        *.tbz2) tar xjf $1 ;;
        *.tgz) tar xzf $1 ;;
        *.zip) unzip $1 ;;
        *.Z) uncompress $1;;
        *.7z) 7z x $1 ;;
        *) echo "'$1' cannot be extracted via ex()" ;;
      esac
      else
        echo "'$1' is not a valid file"
      fi
    }
    
    • Quero fazer também a contraparte inversa, para compactar

    • Eu uso dtrx, que automaticamente extrai o arquivo dentro de uma pasta, o que é ótimo

    • Para mim, aunpack é ainda mais prático

    • Muito elegante

    • Se adicionar inotify e um systemd user service, dá para evoluir mais um nível. Já existe até uma versão empacotada. O que você fez passa um pouco a sensação de reinventar a roda

  • Tenho duas funções que uso sempre para codificar ou cortar mp4. As flags maximizam a compatibilidade em vários ambientes, como WhatsApp e Discord no celular

    ffmp4() {
      input_file="$1"
      output_file="${input_file%.*}_sd.mp4"
    
      ffmpeg -i "$input_file" -c:v libx264 -crf 33 -profile:v baseline -level 3.0 -pix_fmt yuv420p -movflags faststart "$output_file"
    
      echo "Compressed video saved as: $output_file"
    }
    
    ffmp4 foo.webm  # converte para foo_sd.mp4
    
    fftime() {
      input_file="$1"
      output_file="${input_file%.*}_cut.mp4"
      ffmpeg -i "$input_file" -c copy -ss "$2" -to "$3" "$output_file"
    
      echo "Cut video saved as: $output_file"
    }
    
    fftime foo.mp4 01:30 01:45  # gera foo_cut.mp4
    

    fftime corta rápido sem recodificar o original, mas dependendo do vídeo pode haver alguns problemas (por exemplo, não reproduzir). Se quiser recodificar, basta remover -c copy

  • Sempre que crio e testo um alias ou função, acho prático recarregar o ~/.zshrc imediatamente, então uso um alias assim

    alias vz="vim ~/.zshrc && . ~/.zshrc"
    

    E no Mac uso a função abaixo para fazer grep em arquivos docx

    docgrep() {
      mdfind "\"$@\"" -onlyin /Users/xxxx/Notes 2> >(grep --invert-match ' [UserQueryParser] ' >&2) | grep -v -e '/Inactive/' | sort
    }
    

    Também uso a função abaixo para anonimizar a área de transferência do meu Mac antes de colar em canais públicos como ChatGPT ou Slack interno da empresa, para fins de depuração. Quando a função roda, ela mostra a nova versão convertida da área de transferência no stdout, o que permite verificar se algo passou despercebido

    anonymizeclipboard() {
      my_user_id=xxxx
      account_ids="1234567890|1234567890" #regex
      corp_words="xxxx|xxxx|xxxx|xxxx|xxxx" #regex
      project_names="xxxx|xxxx|xxxx|xxxx|xxxx" # regex
      pii="xxxx|xxxx|xxxx|xxxx|xxxx|xxxx" # regex
      hostnames="xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx" # regex
      pbpaste | sed -E -e 's/([0-9]{1,3})\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/\1.x.x.x/g' \
      -e "s/(${corp_words}|${project_names}|${my_user_id}|${pii}|${hostnames})/xxxx/g" -e "s/(${account_ids})/1234567890/g" | pbcopy
      pbpaste
    }
    alias anon=anonymizeclipboard
    
    • Isso é muito bom. Passo por isso com frequência e estava sofrendo por não encontrar uma forma decente de resolver
 
krepe90 2025-10-24

Isso me lembra também de um post que saiu no GeekNews: Ask GN: Vocês têm algum snippet de shell que usam com frequência?