{"id":22180653,"url":"https://github.com/jftuga/chars","last_synced_at":"2025-07-26T17:32:21.919Z","repository":{"id":57651810,"uuid":"448852163","full_name":"jftuga/chars","owner":"jftuga","description":"Determine the end-of-line format, tabs, bom, and nul characters","archived":false,"fork":false,"pushed_at":"2024-01-12T17:24:21.000Z","size":87,"stargazers_count":13,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-06-20T12:40:57.910Z","etag":null,"topics":["bom","command-line","crlf","golang","lf"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jftuga.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-17T10:42:19.000Z","updated_at":"2022-10-18T05:26:35.000Z","dependencies_parsed_at":"2024-01-12T22:52:24.023Z","dependency_job_id":"5b53c628-5b20-4a50-9367-950bed56aec5","html_url":"https://github.com/jftuga/chars","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jftuga%2Fchars","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jftuga%2Fchars/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jftuga%2Fchars/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jftuga%2Fchars/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jftuga","download_url":"https://codeload.github.com/jftuga/chars/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227700378,"owners_count":17806365,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bom","command-line","crlf","golang","lf"],"created_at":"2024-12-02T09:19:01.074Z","updated_at":"2025-07-26T17:32:21.896Z","avatar_url":"https://github.com/jftuga.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# chars\nDetermine the end-of-line format, tabs, bom, and nul characters\n\n## Usage\n\n* For help, run `chars -h`\n\n```\n\nchars v2.6.0\nDetermine the end-of-line format, tabs, bom, and nul\nhttps://github.com/jftuga/chars\n\nUsage:\nchars [filename or file-glob 1] [filename or file-glob 2] ...\n  -F    when used with -f, only display a list of failed files, one per line\n  -b    examine binary files\n  -c    add comma thousands separator to numeric values\n  -e string\n        exclude based on regular expression; use .* instead of *\n  -f string\n        fail with OS exit code=100 if any of the included characters exist; ex: -f crlf,nul,bom8,nonascii\n  -j    output results in JSON format; can't be used with -l; does not honor -t or -c\n  -l int\n        shorten files names to a maximum of this length\n  -s string\n        sort output by column: filename, crlf, lf, tab, nul, bom8, bom16, nonascii, bytesread (default \"filename\")\n  -t    append a row which includes a total for each column\n  -v    display version and then exit\n\nNotes:\nUse - to read a file from STDIN\nOn Windows, try: chars *  -or-  chars */*  -or-  chars */*/*\n```\n\n## Installation\n\n* macOS: `brew update; brew install jftuga/tap/chars`\n* Binaries for Linux, macOS and Windows are provided in the [releases](https://github.com/jftuga/chars/releases) section.\n\n___\n\n## Example 1\n\n* Run `chars` with no additional cmd-line switches\n* * Only report files in the current directory\n* * Report text files only since `-b` is not used\n\n```ps1con\nPS C:\\chars\u003e .\\chars.exe *\n+-----------------+------+-----+-----+------+------+-------+-----------+-----------+\n|    FILENAME     | CRLF | LF  | TAB | NUL  | BOM8 | BOM16 | NON-ASCII | BYTESREAD |\n+-----------------+------+-----+-----+------+------+-------+-----------+-----------+\n| .goreleaser.yml |    0 |  59 |   0 |    0 |    0 |     0 |         0 |      1066 |\n| LICENSE         |    0 |  21 |   0 |    0 |    0 |     0 |         0 |      1068 |\n| README.md       |    0 |  92 |   0 |    0 |    0 |     0 |         0 |      3510 |\n| chars.go        |    0 | 246 | 328 |    0 |    0 |     0 |         0 |      6477 |\n| go.mod          |    0 |  10 |   2 |    0 |    0 |     0 |         0 |       188 |\n| go.sum          |    0 |   6 |   0 |    0 |    0 |     0 |         0 |       533 |\n| testfile1       |    0 |  22 |   0 | 3223 |    0 |     1 |        27 |      6448 |\n+-----------------+------+-----+-----+------+------+-------+-----------+-----------+\n```\n\n## Example 2\n\n* Run `chars` with `-e` and `-l` cmd-line switches\n* * Only report files starting with `p` in the `C:\\Windows\\System32` directory\n* * Exclude all files matching `perf.*dat`\n* * Shorten filenames to a maximum length of `32`\n\n```ps1con\nPS C:\\chars\u003e .\\chars.exe -e perf.*dat -l 32 C:\\Windows\\System32\\p*\n+----------------------------------+------+----+-----+------+------+-------+-----------+-----------+\n|             FILENAME             | CRLF | LF | TAB | NUL  | BOM8 | BOM16 | NON-ASCII | BYTESREAD |\n+----------------------------------+------+----+-----+------+------+-------+-----------+-----------+\n| C:\\Windows\\System32\\pcl.sep      |   11 |  0 |   0 |    0 |    0 |     0 |         0 |       150 |\n| C:\\Windows\\System32\\perfmon.msc  | 1933 |  0 |   0 |    0 |    0 |     0 |         0 |    145519 |\n| C:\\Windows\\Sys...tmanagement.msc | 1945 |  0 |   0 |    0 |    0 |     0 |         0 |    146389 |\n| C:\\Windows\\System32\\pscript.sep  |    2 |  0 |   0 |    0 |    0 |     0 |         0 |        51 |\n| C:\\Windows\\Sys...eryprovider.mof |    0 | 61 |   0 | 2073 |    0 |     1 |       987 |      4148 |\n+----------------------------------+------+----+-----+------+------+-------+-----------+-----------+\n```\n\n## Example 3\n\n* Pipe STDIN to `chars`\n* Use JSON output, with `-j`\n\n```console\n$ curl -s https://example.com/ | chars -j\n```\n\n```json\n[\n    {\n        \"filename\": \"STDIN\",\n        \"crlf\": 0,\n        \"lf\": 46,\n        \"tab\": 0,\n        \"bom8\": 0,\n        \"bom16\": 0,\n        \"nul\": 0,\n        \"nonAscii\": 0,\n        \"bytesRead\": 1256\n    }\n]\n```\n\n## Example 4\n\n* Fail when certain characters are detected, with `-f`\n* * OS exit code on a `-f` failure is always `100`\n* * `-f` is a comma-delimited list containing: `crlf`, `lf`, `tab`, `nul`, `bom8`, `bom16`\n\n```console\n$ chars -f lf,tab /etc/group ; echo $?\n+------------+------+----+-----+-----+------+-------+-----------+-----------+\n|  FILENAME  | CRLF | LF | TAB | NUL | BOM8 | BOM16 | NON-ASCII | BYTESREAD |\n+------------+------+----+-----+-----+------+-------+-----------+-----------+\n| /etc/group |    0 | 58 |   0 |   0 |    0 |     0 |         0 |       795 |\n+------------+------+----+-----+-----+------+-------+-----------+-----------+\n\n100\n```\n\n## Example 5\n* Fail when certain characters are detected, with `-f`\n* Only output failed file names, with `-F`\n\n```console\n$ chars -f lf,tab -F /etc/gr* ; echo $?\n/etc/group\n/etc/group.bak\n\n100\n```\n\n## Example 6\n\n* Output to JSON, with `-j`\n* Use `-e` to exclude and filenames starting with `go`, such as `go.mod` and `go.sum`\n* Use `jq` to output to `CSV` containing two columns: `filename`, `tab`\n* * Only include files that contain `tab` characters\n\n```console\n$ chars -e '^go' -j * | jq -r '.[] | select(.tab \u003e 0) | [.filename,.tab] | @csv'\n\"case.go\",80\n\"chars.go\",475\n```\n\n## Example 7\n* Output totals, with `-t`\n* Output commas in numeric values, with `-c`\n* Exclude files containing `.g*`, with `-e`\n\n```ps1con\nPS C:\\chars\u003e .\\chars.exe -t -c -e \"\\.g.*\" *\n+-----------------+------+-----+-----+-----+------+-------+-----------+-----------+\n|    FILENAME     | CRLF | LF  | TAB | NUL | BOM8 | BOM16 | NON-ASCII | BYTESREAD |\n+-----------------+------+-----+-----+-----+------+-------+-----------+-----------+\n| LICENSE         |    0 |  21 |   0 |   0 |    0 |     0 |         0 |     1,068 |\n| README.md       |    0 | 178 |   4 |   0 |    0 |     0 |         0 |     6,656 |\n| STATUS.md       |    0 |  50 |   0 |   0 |    0 |     0 |         0 |     3,055 |\n| go.mod          |    0 |  11 |   3 |   0 |    0 |     0 |         0 |       214 |\n| go.sum          |    0 |   9 |   0 |   0 |    0 |     0 |         0 |       795 |\n| TOTALS: 5 files |    0 | 269 |   7 |   0 |    0 |     0 |         0 |    11,788 |\n+-----------------+------+-----+-----+-----+------+-------+-----------+-----------+\n```\n\n___\n\n## Reading from STDIN on Windows\n* **YMMV when piping to `STDIN` under Windows**\n* * Under `cmd`, instead of `type input.txt | chars`, use `\u003c` redirection when possible: `chars \u003c input.txt`\n* * Under a recent version of `powershell`, use `Get-Content -AsByteStream input.txt | chars` instead of just `Get-Content input.txt | chars`\n* `cmd` and `powershell` will skip `BOM` characters; these 2 fields will both report a value of `0`\n* `cmd` and `powershell` will skip `NUL` characters; this field report a value of `0`\n* `cmd` will convert `LF` to `CRLF` for `UTF-16` encoded files\n* `powershell` will convert `LF` to `CRLF`\n* Piping from programs such as `curl` will return `LF` characters under `cmd`, but `CRLF` under `powershell`\n* * Under powershell, consider using `curl --output`\n\n## Case Folding on Windows\n* [Case folding](https://www.w3.org/TR/charmod-norm/#definitionCaseFolding) on Windows is somewhat implemented in [case.go](case.go).\n* * This programs attempts case-insensitive filename matching since this is the expected behavior on Windows.\n* * It is hard-coded to `English`.\n\n## Wikipedia\n\n* [Newline](https://en.wikipedia.org/wiki/Newline#Representation) - `CRLF` vs `LF`\n* [Tab key](https://en.wikipedia.org/wiki/Tab_key#Tab_characters)\n* [Null character](https://en.wikipedia.org/wiki/Null_character)\n* [Byte order mark](https://en.wikipedia.org/wiki/Byte_order_mark) - `BOM-8` vs `BOM-16`\n\n## Acknowledgments\n\n* [ellipsis](https://github.com/jftuga/ellipsis) - Go module to insert an ellipsis into the middle of a long string to shorten it\n* [tablewriter](https://github.com/olekukonko/tablewriter) - ASCII table in golang\n* [/u/skeeto](https://old.reddit.com/user/skeeto) and [/u/petreus](https://old.reddit.com/user/ppetreus) provided [code review and suggestions](https://old.reddit.com/r/golang/comments/s64jye/i_wrote_a_cli_tool_to_determine_the_endofline/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjftuga%2Fchars","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjftuga%2Fchars","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjftuga%2Fchars/lists"}