Codificação de Caracteres macOS vs Windows: Como Prevenir Erros de Sincronização
Resumo rápido: neste guia encontra a explicação técnica do problema NFD vs NFC, os cenários de falha mais comuns em OneDrive, SharePoint e NAS, as boas práticas preventivas e um script Python completo para normalizar nomes de ficheiros e pastas no macOS.
Quando um utilizador de macOS guarda um ficheiro chamado Configuração.docx e outro utilizador Windows abre a mesma pasta partilhada, pode ver dois ficheiros em vez de um — ou não ver nenhum. Não é um bug do serviço de sincronização: é uma diferença fundamental na forma como os dois sistemas operativos representam caracteres com acentos a nível de bytes.
Este artigo explica a causa técnica (Unicode NFD vs NFC), os problemas que provoca em OneDrive, SharePoint, Dropbox, Git e NAS com SMB, e como resolver — incluindo um script Python pronto a usar para normalizar pastas inteiras no macOS sem perda de dados.
⚠ Ficheiros duplicados após sync não são erro do OneDrive
Se vê ficheiros como relatorio.docx e relatório.docx em simultâneo após sincronizar entre Mac e Windows, a causa é quase sempre codificação Unicode — o mesmo nome, representado por bytes diferentes, é tratado como dois ficheiros distintos pelo serviço de sync.
Neste artigo
1. NFD vs NFC: a causa técnica do problema
O Unicode define múltiplas formas de representar o mesmo caracter visível. Um ã pode ser guardado como um único code point (U+00E3 — forma composta NFC) ou como dois code points separados: a letra a seguida de um tilde combinante (U+0061 + U+0303 — forma decomposta NFD). O resultado visual é idêntico; os bytes em disco são diferentes.
| Sistema operativo | Normalização | Representação de “ã” | Sistema de ficheiros |
|---|---|---|---|
| macOS (APFS / HFS+) | NFD — decomposto | a + tilde combinante (2 bytes) |
APFS, HFS+ |
| Windows | NFC — composto | ã (1 byte — U+00E3) |
NTFS, FAT32, exFAT |
| Linux / ext4 | Nenhuma (passthrough) | Depende da aplicação que escreveu | ext4, XFS, Btrfs |
O macOS aplica NFD automaticamente ao nível do sistema de ficheiros — qualquer ficheiro criado com um nome acentuado fica guardado em NFD, independentemente da aplicação usada. O Windows usa NFC. Quando um serviço de sincronização compara os dois, calcula hashes diferentes e trata-os como ficheiros distintos.
2. Problemas concretos em sincronização
| Sintoma | Causa | Serviços afectados |
|---|---|---|
| Ficheiros duplicados após sync | NFD e NFC tratados como ficheiros distintos | OneDrive, Dropbox, SharePoint |
| Conflitos fantasma (sem alterações) | Hash difere apesar do conteúdo ser igual | OneDrive, Google Drive, Dropbox |
| Ficheiro desaparece no Windows | Nome contém caracteres proibidos no NTFS | OneDrive, SharePoint, NAS SMB |
| Erro de path too long no Windows | Caminho ultrapassa 260 caracteres (limite NTFS por omissão) | SharePoint (limite 400 chars), OneDrive |
| git status mostra ficheiros alterados sem edições | NFD do Mac vs NFC no repositório remoto | Git, GitHub, Azure DevOps |
3. Caracteres proibidos no Windows NTFS
Além da questão NFD/NFC, o NTFS proíbe um conjunto de caracteres em nomes de ficheiros que o macOS permite livremente. Qualquer ficheiro macOS com estes caracteres no nome não sincroniza para o lado Windows — e frequentemente desaparece sem aviso:
# Caracteres PROIBIDOS no Windows NTFS (válidos no macOS) \ / : * ? " < > | # Nomes reservados pelo Windows (mesmo sem extensão) CON PRN AUX NUL COM1-COM9 LPT1-LPT9 # Outros problemas comuns . nome # ponto inicial = oculto no macOS/Linux, visível no Windows nome. # ponto final = inválido no Windows nome com espaço # espaços no início ou fim do nome # Caracteres adicionais proibidos no SharePoint Online ~ # % & * { } ' "
4. Boas práticas preventivas por serviço
A regra de ouro em ambientes mistos é adoptar NFC + sem caracteres especiais NTFS como convenção de equipa para nomes de ficheiros e pastas. Abaixo estão as configurações específicas por serviço.
Exemplos de nomes seguros vs. problemáticos:
# SEGUROS: sem acentos, sem caracteres especiais relatorio-financeiro-2024.xlsx configuracao-vpn.docx reuniao-equipa-marco-2024.pptx # PROBLEMÁTICOS: acentos + caracteres especiais NTFS relatório financeiro: Q1/2024.xlsx # acentos + dois pontos + barra configuração VPN?.docx # acento + ponto de interrogação Reunião equipa — março 2024.pptx # acento + em dash
| Serviço | Configuração recomendada | Limite a ter em atenção |
|---|---|---|
| OneDrive | Sem configuração especial — evitar caracteres proibidos e caminhos longos | Caminho total < 400 caracteres |
| SharePoint Online | Evitar também: ~ # % & * { } ' " |
Caminho total < 400 chars; nome de ficheiro < 128 chars |
| Dropbox | Cliente Windows normaliza para NFC automaticamente, mas pode criar duplicados se o Mac sincronizar NFD primeiro | Usar Selective Sync durante migração |
| NAS Synology (SMB) | DSM → Serviços de Ficheiros → SMB → activar Support unicode NFD encoding | Resolve a maioria dos problemas com clientes macOS |
| Windows (Long Path) | Activar suporte a caminhos longos via Group Policy ou registo | Disponível desde Windows 10 1607 |
# Activar suporte a caminhos longos no Windows (PowerShell como admin) Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 # Via Group Policy (para domínios AD): # Computer Configuration → Administrative Templates → System → Filesystem # → Enable Win32 long paths → Enabled
5. Script Python: normalizar pastas no macOS
O script fix_accents.py percorre uma pasta e todas as suas subpastas, remove acentos e diacríticos dos nomes de ficheiros e pastas, e elimina caracteres proibidos no NTFS. Funciona com o Python 3 incluído no macOS — sem dependências externas.
🛑 O erro já aconteceu? Faz backup antes de qualquer acção
Se tens ficheiros duplicados, nomes corrompidos ou itens em falta depois de uma sincronização, não tentes corrigir imediatamente. A renomeação em massa é irreversível — um conflito não detectado pode sobrepor dados. O procedimento seguro é:
- Pausar a sincronização do OneDrive / Dropbox / Google Drive antes de tocar em qualquer ficheiro
- Fazer backup completo da pasta afectada para um destino externo (Time Machine, disco externo ou cópia manual para outra localização)
- Verificar o backup antes de continuar — confirmar que todos os ficheiros estão acessíveis na cópia
- Só depois executar o script com
--dry-runpara avaliar as alterações - Aplicar as alterações e reactivar a sincronização apenas após validar o resultado
📌 Opção rápida de backup no macOS antes de executar o script:
cp -R ~/Documents/Projecto ~/Desktop/Projecto_backup_$(date +%Y%m%d)
💡 Executar sempre –dry-run primeiro
O modo de simulação mostra todas as alterações que seriam feitas sem renomear nada. É a forma segura de validar o resultado antes de aplicar. O script pede confirmação explícita antes de qualquer alteração real e detecta conflitos de nomes automaticamente.
Utilização:
# Passo 1: Simular sem alterar nada (sempre primeiro) python3 fix_accents.py ~/Documents/Projecto --dry-run # Passo 2: Aplicar as alterações (pede confirmação) python3 fix_accents.py ~/Documents/Projecto # Com log de todas as alterações para ficheiro python3 fix_accents.py ~/Documents/Projecto --log alteracoes.txt # Manter maiúsculas/minúsculas originais (por omissão converte para minúsculas) python3 fix_accents.py ~/Documents/Projecto --no-lowercase
Exemplos de transformações aplicadas pelo script:
| Nome original (macOS NFD) | Resultado (NFC seguro) | O que foi corrigido |
|---|---|---|
| Configuração/ | Configuracao/ | Diacrítico ã → a, ç → c |
| relatório final.docx | relatorio-final.docx | ó → o, espaço → hífen |
| Q1: Resultados?.xlsx | Q1-Resultados.xlsx | : e ? removidos (NTFS) |
| café — março.txt | cafe-marco.txt | é → e, em-dash → hífen, ç → c |
| .DS_Store, ._ficheiro | Ignorado | Ficheiros de sistema macOS nunca são tocados |
| nome (já existe) | Conflito detectado | Avisa e salta — nunca sobrescreve |
Código do script (fix_accents.py):
#!/usr/bin/env python3 # fix_accents.py — Remove acentos e caracteres especiais de nomes de # ficheiros e pastas para compatibilidade macOS/Windows (NFD → ASCII seguro) # Não requer dependências externas — funciona com Python 3 nativo do macOS import os, sys, re, unicodedata, argparse, logging from pathlib import Path from datetime import datetime # Mapeamento de caracteres especiais sem equivalente ASCII directo EXTRA_MAP = { '–': '-', # en dash '—': '-', # em dash 'ª': 'a', # ordinal feminino ª 'º': 'o', # ordinal masculino º 'ß': 'ss', # ß 'æ': 'ae', # æ 'ø': 'o', # ø '…': '.', # reticências … } NTFS_FORBIDDEN = r'[\/:*?"<>|]' def slugify_name(name, lowercase=False): if name.startswith('.'): return name # preservar ficheiros ocultos stem, *ext = name.rsplit('.', 1) if '.' in name else (name,) ext = ('.' + ext[0]) if ext else '' r = unicodedata.normalize('NFC', stem) for src, dst in EXTRA_MAP.items(): r = r.replace(src, dst) r = unicodedata.normalize('NFD', r) r = ''.join(c for c in r if unicodedata.category(c) != 'Mn') r = re.sub(NTFS_FORBIDDEN, '', r) r = re.sub(r'[\s]+', '-', r) r = re.sub(r'[^\w\-.]', '', r) r = re.sub(r'-{2,}', '-', r).strip('-').strip('.') or 'ficheiro' if lowercase: r, ext = r.lower(), ext.lower() return r + ext def process_directory(root, dry_run, lowercase, logger): renamed = errors = unchanged = 0 for dirpath, dirnames, filenames in os.walk(root, topdown=False): cur = Path(dirpath) for name in filenames + dirnames: if name in ('.DS_Store', '.localized') or name.startswith('._'): continue new = slugify_name(name, lowercase) if new == name: unchanged += 1; continue old_p, new_p = cur / name, cur / new if new_p.exists() and new_p != old_p: print(f' CONFLITO {name} → {new} (ignorado)'); errors += 1; continue if dry_run: print(f' DRY-RUN {name} → {new}'); renamed += 1 else: try: old_p.rename(new_p); print(f' OK {name} → {new}'); renamed += 1 except Exception as e: print(f' ERRO {name}: {e}'); errors += 1 return renamed, errors, unchanged def main(): p = argparse.ArgumentParser() p.add_argument('path'); p.add_argument('--dry-run', action='store_true') p.add_argument('--no-lowercase', action='store_true'); p.add_argument('--log') args = p.parse_args() root = Path(args.path).expanduser().resolve() if not root.is_dir(): print(f'Erro: {root} não é uma pasta'); sys.exit(1) logger = logging.getLogger('fix_accents') if args.log: fh = logging.FileHandler(args.log, encoding='utf-8') fh.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s')) logger.addHandler(fh); logger.setLevel(logging.DEBUG) print(f' Pasta: {root}') print(f'Modo: {"DRY-RUN" if args.dry_run else "REAL"} ') if not args.dry_run: r = input('ATENÇÃO: operação irreversível. Tens backup? (s/N): ').strip().lower() if r not in ('s','sim','y','yes'): print('Cancelado.'); sys.exit(0) renamed, errors, unchanged = process_directory(root, args.dry_run, not args.no_lowercase, logger) print(f' {"Seriam renomeados" if args.dry_run else "Renomeados"}: {renamed}') print(f'Sem alterações: {unchanged} | Erros/Conflitos: {errors} ') if __name__ == '__main__': main()
6. Configuração Git para ambientes mistos
O Git tem um comportamento específico em relação a NFD/NFC que afecta repositórios partilhados entre utilizadores de macOS e Windows. Sem a configuração correcta, o git status mostra ficheiros como modificados em Macs, mesmo sem qualquer edição de conteúdo.
# Aplicar globalmente em todos os repositórios Git do Mac git config --global core.precomposeunicode true # força NFC nos nomes de ficheiros git config --global core.quotepath false # mostra acentos no terminal sem escape # Verificar a configuração actual git config --global --list | grep -E "unicode|quote" # Para um repositório específico já existente cd /caminho/para/repositorio git config core.precomposeunicode true # Detectar ficheiros NFD no repositório (mostra nomes com escape Ã\...) git ls-files | cat -v | grep '\\' # Verificar se o .gitattributes está a normalizar correctamente # Adicionar ao .gitattributes do projecto: * text=auto eol=lf
7. Problemas comuns e resolução
| Problema | Causa | Resolução |
|---|---|---|
| Ficheiros duplicados após sincronizar | NFD (Mac) vs NFC (Windows) tratados como ficheiros distintos | Executar fix_accents.py no Mac antes de sincronizar; adoptar política de nomes sem acentos |
| Ficheiro criado no Mac não aparece no Windows | Nome contém : * ? < > | (proibidos no NTFS) |
Renomear o ficheiro no Mac removendo os caracteres problemáticos; usar o script com --dry-run para identificar |
| git status mostra alterações sem edições | NFD do Mac vs NFC no repositório remoto | git config --global core.precomposeunicode true |
| Erro 0x8007007B no OneDrive (nome inválido) | Caractere proibido no NTFS no nome do ficheiro ou pasta | Identificar com o script em modo --dry-run e renomear; o OneDrive bloqueia o ficheiro até ser corrigido |
| NAS Synology mostra nomes corrompidos no Mac | SMB não está configurado para suporte NFD | DSM → Serviços de Ficheiros → SMB → activar Support unicode NFD encoding |
| Script Python diz “Conflito detectado” | Já existe um ficheiro com o nome normalizado na mesma pasta | Resolver manualmente: verificar qual o ficheiro a manter, eliminar o duplicado e voltar a executar o script |
✓ Checklist para ambientes mistos macOS / Windows
- Se o erro já ocorreu: pausar a sync, fazer backup completo da pasta afectada antes de qualquer acção —
cp -R ~/pasta ~/Desktop/pasta_backup_$(date +%Y%m%d) - Política de equipa: nomes de ficheiros sem acentos e sem caracteres especiais NTFS
git config --global core.precomposeunicode trueem todos os Macs- NAS Synology: SMB com Support unicode NFD encoding activado
- SharePoint: verificar limite de 400 caracteres no caminho total
- Windows: activar Long Path Support (LongPathsEnabled = 1)
- Executar
fix_accents.py --dry-runantes de qualquer migração de ficheiros
Artigos relacionados no kbase.pt
Leituras complementares
FAQ
Porquê é que o macOS usa NFD em vez de NFC?
O sistema de ficheiros HFS+ da Apple foi desenhado para usar NFD como normalização canónica. O APFS manteve este comportamento por compatibilidade. É uma decisão de design histórica que não implica que um sistema seja mais correcto que o outro — ambos os formatos são Unicode válido.
O script altera o conteúdo dos ficheiros?
Não. O script fix_accents.py altera exclusivamente os nomes de ficheiros e pastas — nunca o conteúdo interno dos ficheiros. Um .docx, .xlsx ou .pdf com texto acentuado fica intacto.
Posso usar o script em pastas já sincronizadas com o OneDrive activo?
Sim, mas recomenda-se pausar a sincronização do OneDrive antes de executar o script e reactivá-la depois. Renomear ficheiros com o cliente de sincronização activo pode gerar conflitos desnecessários durante o processo.
