1 pontos por GN⁺ 2024-05-02 | 1 comentários | Compartilhar no WhatsApp
  • ffs(file filesystem) é uma ferramenta que monta dados semiestruturados como JSON, YAML e TOML como um sistema de arquivos para que possam ser explorados e editados com ferramentas de shell Unix
  • O shell Unix é rico em ferramentas de processamento de strings, mas como sua estrutura de dados básica é o sistema de arquivos, ele não se adapta tão bem à edição de dados em forma de árvore
  • ffs [file] conecta um arquivo a um ponto de montagem e, ao desmontar, envia o resultado atualizado para stdout ou para um arquivo de saída especificado
  • Escritas em arquivos e criação de diretórios são convertidas em chaves e objetos JSON, e 1, true, false e arquivos vazios são refletidos respectivamente como número, booleanos e valor null
  • No Linux é necessário FUSE, no macOS é necessário macFUSE, e ele pode não ser adequado para Windows, ambientes onde FUSE não pode ser usado, tarefas apenas de busca ou arquivos muito grandes

Tratar dados semiestruturados como diretórios

  • ffs é a sigla de file filesystem e monta dados semiestruturados como um sistema de arquivos para permitir o trabalho com ferramentas de shell já conhecidas
  • Os formatos atualmente suportados são JSON, YAML, TOML, e há planos para oferecer suporte a mais formatos
  • O uso detalhado pode ser consultado na ffs manpage

Fluxo de montagem e edição

  • A execução padrão é ffs [file], que monta file.blah no ponto de montagem file e imprime a versão final atualizada em stdout
  • Com ffs -m MOUNT file é possível definir explicitamente o ponto de montagem, e com -o OUTPUT especificar o arquivo de saída
  • ffs -i file edita o arquivo no local, e ao desmontar o volume o resultado é gravado novamente em file
  • Regras de conversão mostradas no exemplo

    • echo Mikey Indiana >object/name altera o valor name no JSON
    • echo 1 >object/nose é refletido como o número 1, e não como string
    • mkdir object/pockets e os arquivos dentro dele são convertidos em um objeto JSON
    • O arquivo vazio mistakes é registrado como null no JSON

Requisitos de instalação e distribuição

  • No Linux, FUSE é necessário
  • No macOS, macFUSE é necessário
  • Os builds de desenvolvimento mais recentes são fornecidos como executáveis únicos para Linux e macOS
  • Versões específicas podem ser conferidas na release page, e a versão atual é 0.1.2
  • Também é possível compilar a partir do source

Materiais relacionados e pontos de comparação

  • Há o artigo da PLOS 2021 “Files-as-Filesystems for POSIX Shell Data Processing”
  • jq e gron são ferramentas para lidar com JSON na linha de comando
  • O diferencial do ffs é suportar vários formatos, permitir edição com ferramentas de shell familiares e não exigir o aprendizado de uma nova linguagem
  • Uso no Windows, impossibilidade de usar FUSE, tarefas que exigem apenas busca e arquivos muito grandes podem não combinar com o ffs
  • A licença é GPLv3

1 comentários

 
GN⁺ 2024-05-02
Comentários do Hacker News
  • Isso é legal. Recentemente, envolvi a libfuse em Nim e portei o exemplo de sistema de arquivos hello, e acabei criando algo quase igual
    Na minha versão, é preciso alimentar os dados por pipe e especificar o ponto de montagem; quando termina, o resultado é escrito na saída padrão. Então dá para encaixar em uma cadeia de pipes, mas você também precisa cuidar da saída
    Agora estou explorando se dá para transformar outras coisas em sistemas de arquivos. Também fiz uma barra de status para o gerenciador de janelas Nimdow: quando você escreve conteúdo em arquivos individuais, uma barra com blocos é gerada como saída, o que facilita substituir o conteúdo da barra
    Outra ferramenta que criei é um player de música baseado em libvlc. Você passa uma pasta, ele lê as mídias com tags ID3 e organiza pastas como by-artist e by-album. Cada arquivo se chama - e contém o caminho completo do arquivo real. Para tocar uma música, você faz algo como dar cat em um arquivo para control/current e escrever play em control/command. Há mais recursos e comandos de playlist, mas o objetivo é criar um player de música muito fácil de controlar por scripts

    • Uma ideia: montar recursivamente arquivos de código ou projetos. Com algo como tree-sitter, daria para extrair definições de classes e funções e criar cada uma como um “arquivo” dentro de um diretório que representa o arquivo real
      Se quiser entender a estrutura da base de código, basta rodar tree :)
      Indo mais fundo, talvez dê até para resolver imports como links simbólicos etc.; há muitas possibilidades interessantes
    • Fiquei curioso para saber se você pode compartilhar o código em Nim. Faz um tempo que quero fazer algo com FUSE, e estou usando Nim em alguns projetos
    • Acho que seria bom ter uma forma embutida de expor facilmente informações de processos como um sistema de arquivos
      Por exemplo, fazer cat /proc/$pid/fs/current_track para obter o nome da música atual de um player, ou ls /proc/$pid/fs/tabs para ver a lista de abas abertas de um navegador. Talvez até fosse possível obter HTML ou imagens embutidas
      Hoje isso já é possível com FUSE, mas é trabalhoso, então ninguém faz
  • Acho útil o suficiente para virar um recurso padrão no nível do sistema operacional
    Sistemas operacionais Unix-like permitem montar imagens de disco para navegar pelo conteúdo. Mas, se você explora arquivos dentro de arquivos, há muitos outros formatos úteis. Arquivos compactados são o exemplo clássico
    Alguns gerenciadores de arquivos dão suporte a isso, mas acho que a camada de aplicação não é o lugar ideal. Parece algo que poderia ser implementado como drivers por tipo de arquivo

    • O que realmente é necessário é uma forma de escrever comandos de montagem para cada formato de arquivo e um comando separado que detecte o formato e despache para o handler adequado. Provavelmente seria parecido com o comando file, e tudo deveria ser possível no espaço de usuário
      O único fator que impede isso hoje é que o MacOS não expõe uma API de sistema de arquivos em espaço de usuário. No Linux, Windows e BSD isso já é possível
      Se algum desenvolvedor da Apple estiver lendo: extensões de provedor de arquivos não bastam. Deem-nos um equivalente ao FUSE. Sei que ele existe
    • Já existe o avfs. Ele faz isso como um sistema de arquivos FUSE. O uso não é dos mais intuitivos, mas funciona e também é extensível
      https://avf.sourceforge.net/
    • Isso era um recurso central de projeto do reiserfsv4, mas o Linux acabou se recusando a fazer o merge. O assassinato da esposa provavelmente também não ajudou
    • Pergunto sinceramente: como isso é útil? Não vejo muito bem casos de uso em que isso realmente teria utilidade
    • Eu achava que o archivemount já fazia isso; estou deixando passar alguma coisa?
      De qualquer forma, mesmo que não seja exatamente o que você quer, FUSE é um mecanismo mais geral e parece permitir fazer o que você quiser, e talvez até mais
  • Também dá para montar commits do git como um sistema de arquivos
    https://jvns.ca/blog/2023/12/04/mounting-git-commits-as-fold...
    Post anterior: https://news.ycombinator.com/item?id=38527866

    • Agora só falta uma pilha gigantesca de regras para escolher qual revisão usar, e aí vira aquele demônio profano chamado Rational ClearCase
  • Pelo título, fiquei animado achando que era algo que eu já tinha procurado antes ou pensado em criar. Talvez seja um bom lugar para perguntar
    Existe algum sistema de arquivos FUSE que, enquanto montado, funcione em memória como tmpfs e, ao desmontar, serialize tudo em um único arquivo no disco?
    O mais próximo são drivers FUSE que montam arquivos de archive, mas aí é difícil obter coisas como links simbólicos

    • O mais próximo que encontrei é https://github.com/guardianproject/libsqlfs
      libsqlfs implementa um sistema de arquivos estilo POSIX sobre um banco de dados SQLite. Ele fornece um sistema de arquivos de leitura/escrita com sua própria hierarquia e namespace dentro de um único arquivo, e pode ser usado como biblioteca compartilhada ou módulo FUSE
    • Não é puramente em memória, mas talvez algo como https://github.com/jrwwallis/qcow2fuse funcione
      Comparado ao DMG do OSX é tosco, mas, sendo generoso, cumpre um propósito parecido
      Ou talvez dê para envolver tmpfs e, ao desmontar, serializar para um tarball preservando links simbólicos
    • Por que precisa estar em memória?
      Você provavelmente já sabe, mas há muitos cenários realistas em que descarregar buffers só ao desmontar pode levar à corrupção de dados
      Ainda assim, o problema que você está tentando resolver parece interessante
    • Precisa mesmo ser FUSE? Não daria para montar uma imagem de disco por loopback?
    • Não me vem à cabeça exatamente algo assim, mas acho que copiar um arquivo de imagem para /tmp, usá-lo e depois de desmontar movê-lo para o disco chegaria bem perto
  • Também existe o Parts-of-file File System: https://www.usenix.org/conference/2005-usenix-annual-technic...

  • Isso me lembra o TabFS, do Omar Rizwan: <https://omar.website/tabfs/>

  • Fiz isso em 2003. Surpreendentemente, era rápido e facilitava fazer bloqueios granulares
    Usei como banco de dados por usuário em uma linguagem de templates web para uma ferramenta enorme de criação de sites

  • Quando vi o título, achei que fosse um meme
    Mas é uma ideia realmente inteligente. Pessoalmente, faço a maior parte do processamento de dados em linguagens de nível mais alto, então não sei se eu usaria diretamente, mas imagino que haverá pessoas encontrando casos de uso
    É uma boa abordagem de pensar fora da caixa

  • Parece muito bom, e preciso experimentar o quanto antes
    Acho que pode ser bem útil para navegar ou pesquisar dentro de arquivos JSON

  • Se isso parece interessante, talvez você também se interesse pelo Solvent-Configr
    https://aws.amazon.com/marketplace/pp/prodview-i3ym46leenag4
    Modelando objetos por meio de um mecanismo de sistema de arquivos, é possível projetar soluções baseadas em objetos que suportam navegação no estilo de sistema de arquivos
    Demo: https://youtu.be/XgTgubZQPHw