Se apareceu sed: 1: "s/foo/bar/g": invalid command code, nada está quebrado. O macOS traz utilitários BSD e seu script foi escrito para GNU. Mesmos nomes, flags diferentes. Estas são as seis que realmente mordem.
1. No macOS o sed -i exige um argumento
$ clai substitua foo por bar direto no config.txt, funcionando no mac e no linux→ sed -i.bak 's/foo/bar/g' config.txt # portável: gera config.txt.bak
O GNU trata o sufixo de backup como opcional; o BSD exige. sed -i '' 's/…' funciona no macOS e falha no Linux. sed -i.bak funciona nos dois — você só fica com um backup para apagar.
2. Regex estendida: use -E, nunca -r
$ clai troque qualquer sequência de dígitos por N usando regex estendida→ echo "foo123" | sed -E 's/[0-9]+/N/'fooN
-r é exclusivo do GNU. -E funciona nos dois — o GNU aceita há anos. Faça do -E o seu padrão e uma classe inteira de bugs desaparece.
3. date: -d no Linux, -r no macOS
$ clai converta o timestamp unix 1735689600 para uma data legível em UTC→ date -u -d @1735689600 '+%Y-%m-%d %H:%M:%S UTC' # GNU2025-01-01 00:00:00 UTC→ date -u -r 1735689600 '+%Y-%m-%d %H:%M:%S UTC' # BSD / macOS
Aqui não existe forma portável. Ramifique pelo uname ou instale o GNU coreutils e chame gdate.
4. stat: -c no Linux, -f no macOS
$ clai imprima o tamanho e o nome deste arquivo→ stat -c '%s %n' t.txt # GNU4 t.txt→ stat -f '%z %N' t.txt # BSD / macOS
Muda a flag e os especificadores de formato. Se o script faz algo não trivial com stat, use find -printf no Linux ou wc -c quando precisar de portabilidade.
5. grep -P não existe no macOS
$ clai extraia só os dígitos desta string, de forma portável→ echo "abc123" | grep -Eo '[0-9]+'123
grep -P (regex Perl) é uma opção de compilação do GNU e o macOS não a inclui. -E cobre a maioria dos padrões reais; se você precisa mesmo de lookahead, precisa de perl ou ripgrep, não de grep.
6. xargs -r é só do GNU — e você precisa dele
$ clai ache .log com mais de 30 dias e apague, sem rodar rm com lista vazia→ find . -name '*.log' -mtime +30 -print0 | xargs -0 -r rm
Sem -r, o xargs do GNU executa o comando uma vez sem argumento nenhum quando a entrada é vazia — é assim que xargs rm num diretório vazio vira erro e xargs docker rm vira surpresa. O xargs do BSD já não roda com entrada vazia, então lá o -r é desnecessário e em versões antigas nem é reconhecido.
Pegadinhas
brew install coreutilsinstala gêmeos com prefixog—gsed,gdate,gstat. Colocargnubinno PATH faz o Mac se comportar como Linux: conserta o seu laptop e esconde o bug do resto do time.- Não conte com
readlink -f. Em macOS antigos ele não existe. Userealpathonde houver, ougreadlink -f. base64 -dversus-D. O GNU decodifica com-d; o macOS historicamente quer-D.
Perguntas relacionadas
O que significa «invalid command code» de verdade? O sed do BSD engoliu a palavra seguinte como sufixo de backup e leu o resto da sua expressão como um comando que não conhece. É vítima do parsing de argumentos, não problema de regex.
macOS é BSD ou Linux? Nenhum dos dois. O userland descende do FreeBSD, por isso as ferramentas compartilham nome com as do Linux mas não as flags.
Como escrevo um script que roda nos dois? Fique em flags POSIX, prefira -E, escreva sempre sed -i.bak e teste nos dois antes de chegar na CI.
Veja também
- O mesmo fluxo no Windows: paridade com PowerShell e cmd
- Triagem de rede em linguagem simples: conexões, portas, DNS
- Do one-liner ao script versionado: quando promover
O CliAI detecta o sistema e o shell em que você está e gera as flags que aquela máquina realmente aceita. Instale em uma linha.