Si te salió sed: 1: "s/foo/bar/g": invalid command code, no hay nada roto. macOS trae utilidades BSD y tu script se escribió para GNU. Mismos nombres, flags distintos. Estas son las seis que de verdad muerden.
1. sed -i exige un argumento en macOS
$ clai reemplaza foo por bar en config.txt in situ, que funcione en mac y en linux→ sed -i.bak 's/foo/bar/g' config.txt # portable: crea config.txt.bak
GNU considera opcional el sufijo de respaldo; BSD lo exige. sed -i '' 's/…' funciona en macOS y falla en Linux. sed -i.bak funciona en ambos: solo te queda un backup que borrar.
2. Expresiones extendidas: usa -E, nunca -r
$ clai sustituye cualquier secuencia de dígitos por N con regex extendida→ echo "foo123" | sed -E 's/[0-9]+/N/'fooN
-r es exclusivo de GNU. -E funciona en ambos: GNU lo acepta desde hace años. Haz de -E tu opción por defecto y desaparece toda una clase de errores.
3. date: -d en Linux, -r en macOS
$ clai convierte el timestamp unix 1735689600 a una fecha legible en 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
Aquí no hay forma portable. Ramifica según uname, o instala GNU coreutils y llama a gdate.
4. stat: -c en Linux, -f en macOS
$ clai imprime el tamaño y el nombre de este archivo→ stat -c '%s %n' t.txt # GNU4 t.txt→ stat -f '%z %N' t.txt # BSD / macOS
Cambia el flag y los especificadores de formato. Si tu script hace algo no trivial con stat, usa find -printf en Linux o wc -c cuando necesites portabilidad.
5. grep -P no existe en macOS
$ clai extrae solo los dígitos de esta cadena, de forma portable→ echo "abc123" | grep -Eo '[0-9]+'123
grep -P (regex de Perl) es una opción de compilación de GNU y macOS no la incluye. -E cubre casi todos los patrones reales; si de verdad necesitas lookahead, necesitas perl o ripgrep, no grep.
6. xargs -r es solo de GNU, y lo necesitas
$ clai busca .log de más de 30 días y bórralos, sin ejecutar rm con una lista vacía→ find . -name '*.log' -mtime +30 -print0 | xargs -0 -r rm
Sin -r, el xargs de GNU ejecuta el comando una vez sin argumentos con entrada vacía: así xargs rm en un directorio vacío acaba en error y xargs docker rm en sorpresa. El xargs de BSD ya no se ejecuta con entrada vacía, así que allí -r sobra y en versiones antiguas ni se reconoce.
Trampas
brew install coreutilsinstala gemelos con prefijog—gsed,gdate,gstat. Añadirgnubinal PATH hace que el Mac se comporte como Linux: arregla tu portátil y esconde el bug del resto del equipo.- No des por hecho
readlink -f. En macOS antiguos no existe. Usarealpathdonde esté, ogreadlink -f. base64 -dfrente a-D. GNU decodifica con-d; macOS históricamente quiere-D.
Preguntas relacionadas
¿Qué significa realmente «invalid command code»? El sed de BSD se comió la siguiente palabra como sufijo de respaldo y leyó el resto de tu expresión como un comando que no conoce. Es una víctima del análisis de argumentos, no un problema de regex.
¿macOS es BSD o Linux? Ninguno. Su espacio de usuario desciende de FreeBSD, por eso las herramientas comparten nombre con las de Linux pero no los flags.
¿Cómo escribo un script que funcione en ambos? Cíñete a flags POSIX, prefiere -E, escribe siempre sed -i.bak y pruébalo en los dos antes de que llegue a CI.
Ver también
- El mismo flujo en Windows: paridad con PowerShell y cmd
- Diagnóstico de red en lenguaje natural: conexiones, puertos, DNS
- Del one-liner al script versionado: cuándo dar el salto
CliAI detecta tu sistema y tu shell y genera los flags que esa máquina acepta de verdad. Instálalo en una línea.