Command-line utility for Linux, macOS and Windows performing sophisticated search and replace followed by calling external executables. It can be considered a kind of JSON shell.
Key features:
- reads multiple substitution rules from a JSON5 file with the extension .xnx (using the json5 package);
- implements loops and conditional processing (if-then-else);
- allows staged (chained) rules in .xnx files;
- allows importing (embedding) other .xnx files into a given one (either entire or filtered with an XPATH query);
- supports an application configuration file with the extension .xnxconfig that allows redefining all keywords (keys with special meaning in .xnx files);
- calls any external executables after all placeholders (keys) are replaced with the final values.
- has Azure DevOps extension in a separate project;
- produces multiple configuration files from a single source based on rules;
- produces Flutter application icons as multiple .png files for all platforms from two .svg files (foreground and background);
- produces light and dark multi-dimensional icons from a single .svg file: .icns for macOS, and .ico for Windows;
- natively supports decompression via the archive package for .zip, .tar, [.tar].gz, [.tar].bz2, [.tar].Z;
- performs search and replace with the multiple outputs in the MS Office files: .docx, .pptx, .xlsx (aka mail merge);
- resolves environment variables in every rule;
- allows passing arbitrary arguments to .xnx files;
- resolves paths in every rule depending on OS it runs under;
- implements in .xnx files commonly needed functions: trim, substr, regex match and replace, full path, file size, date/time math, and many more.
Supported encodings: UTF-8
Planning to add: UTF-16LE, UTF-16BE, UTF-32LE and UTF-32BE via the utf_ext package.
Usage:
xnx [OPTIONS] -h, --help - this help screen -c, --app-config=FILE - application configuration file in JSON5 format https://json5.org/; defaults to default.xnxconfig in the directory where .xnx file is from -x, --xnx=FILE - the actual JSON5 file to process (the ruleset), see https://json5.org/; default extension: .xnx -d, --dir=DIR - directory to start in; if -x, --xnx option is omitted, the application will take the first .xnx file in this directory and use that as primary ruleset -i, --import-dir=DIR - default directory for .xnx files being imported into other .xnx files, the application will export the environment variable _XNX_IMPORT_DIR -m, --escape=MODE - how to escape special characters before the expansion: quotes, xml, html (default: none), the application will export the environment variable _XNX_ESCAPE -q, --quiet - quiet mode (no output, same as verbosity 0), the application will export the environment variable _XNX_QUIET -v, --verbose - shows detailed log, the application will export the environment variable _XNX_VERBOSE, -e, --each - treat each plain argument independently (e.g. can pass multiple filenames as arguments) see also -a, --xargs -a, --xargs - similar to -e, --each, but reads arguments from stdin useful in a pipe with a file path finding command -l, --list-only - display all commands, but do not execute those; if no command specified, then show config, the application will export the environment variable _XNX_LIST_ONLY -s, --append-sep - append record separator "," when filtering input config file (for "list-only" exclusively), the application will export the environment variable _XNX_APPEND_SEP -f, --force - ignore timestamps and force conversion, the application will export the environment variable _XNX_FORCE -p, --compression=LEVEL - compression level for archiving-related operations (1..9) excepting BZip2, the application will export the environment variable _XNX_COMPRESSION -W, --wait-always - always wait for a user to press <Enter> upon completion -w, --wait-err - wait for a user to press <Enter> upon unsuccessful completion --find - just find recursively all files and sub-directories matching the glob pattern in a given or the current directory and print those to stdout --print - just print the arguments to stdout --env - just print all environment variables to stdout --pwd - just print the current working directory to stdout --copy - just copy file(s) and/or directorie(s) passed as plain argument(s), glob patterns are allowed --copy-newer - just copy more recently updated file(s) and/or directorie(s) passed as plain argument(s), glob patterns are allowed --move - just move file(s) and/or directorie(s) passed as plain argument(s), glob patterns are allowed --move-newer - just move more recently updated file(s) and/or directorie(s) passed as plain argument(s), glob patterns are allowed --rename - just the same as --move --rename-newer - just the same as --move-newer --mkdir - just create directories passed as plain arguments --delete - just delete file(s) and/or directorie(s) passed as plain argument(s), glob patterns are allowed --remove - just the same as --delete --bz2 - just compress a single source file to a single destination BZip2 file, can be used with --move --unbz2 - just decompress a single BZip2 file to a single destination file, can be used with --move --gz - just compress a single source file to a single GZip file, can be used with --move --ungz - just decompress a single GZip file to a single destination file, can be used with --move --tar - just create a single destination archive file containing source files and/or directories, can be used with --move --untar - just untar a single archive file to a destination directory, can be used with --move --tarbz2 - just a combination of --tar and --bz2, can be used with --move --untarbz2 - just a combination of --untar and --unbz2, can be used with --move --targz - just a combination of --tar and --gz, can be used with --move --untargz - just a combination of --untar and --ungz, can be used with --move --tarz - just a combination of --tar and --Z, can be used with --move --untarz - just a combination of --untar and --unz, can be used with --move --zip - just zip source files and/or directories to a single destination archive file, can be used with --move to delete the source --unzip - just unzip single archive file to destination directory, can be used with --move to delete the source --z - just compress a single source file to a single Z file, can be used with --move to delete the source --unz - just decompress a single Z file to a single destination file, can be used with --move to delete the source --pack - just compress source files and/or directories to a single destination archive file depending on its extension, can be used with --move --unpack - just decompress a single source archive file to destination files and/or directories depending on the source extension, can be used with --move