{"id":13587337,"url":"https://github.com/ko1nksm/readlinkf","last_synced_at":"2025-03-21T14:31:26.738Z","repository":{"id":52075486,"uuid":"185014778","full_name":"ko1nksm/readlinkf","owner":"ko1nksm","description":"Portable POSIX compliant readlink -f implementation for shell scripts","archived":false,"fork":false,"pushed_at":"2021-01-04T08:23:56.000Z","size":67,"stargazers_count":57,"open_issues_count":4,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-19T22:11:42.695Z","etag":null,"topics":["bash","posix","readlink","realpath","shell"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ko1nksm.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}},"created_at":"2019-05-05T10:12:38.000Z","updated_at":"2025-01-02T15:47:13.000Z","dependencies_parsed_at":"2022-09-06T07:43:00.713Z","dependency_job_id":null,"html_url":"https://github.com/ko1nksm/readlinkf","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ko1nksm%2Freadlinkf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ko1nksm%2Freadlinkf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ko1nksm%2Freadlinkf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ko1nksm%2Freadlinkf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ko1nksm","download_url":"https://codeload.github.com/ko1nksm/readlinkf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244815185,"owners_count":20514911,"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":["bash","posix","readlink","realpath","shell"],"created_at":"2024-08-01T15:06:09.839Z","updated_at":"2025-03-21T14:31:26.148Z","avatar_url":"https://github.com/ko1nksm.png","language":"Shell","funding_links":[],"categories":["Shell"],"sub_categories":[],"readme":"# POSIX compliant readlink -f\n\nPOSIX compliant `readlink -f` implementation for POSIX shell scripts.\n\n## Why?\n\nThe `readlink` and the `realpath` commands are not specified POSIX and some environments may not be installed.\nThere are many implementation alternatives to `readlink -f` ([\\[1\\]][1], [\\[2\\]][2], [\\[3\\]][3]).\nSome of them probably work, but It has some edge case bugs, unresolved issues,\nno tests, poor performance, long code, bashism, non-POSIX compliant and license problem.\nThis feature is important to access files on relative paths from the main script.\nI couldn't find any reliable code despite of.\n\n[1]: https://stackoverflow.com/questions/1055671/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-mac\n[2]: https://stackoverflow.com/questions/59895/how-to-get-the-source-directory-of-a-bash-script-from-within-the-script-itself\n[3]: https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself\n\n## readlinkf\n\nSource code: [readlinkf.sh](readlinkf.sh)\n\nShort code version has been temporarily removed. See [v1.0.0](https://github.com/ko1nksm/readlinkf/releases/tag/v1.0.0) if you need it.\n\n### Usage\n\n  1. `varname=$(readlinkf_* \"\u003cpath\u003e\")` (assign to variable)\n  2. `(readlinkf_* \"\u003cpath\u003e\")` (output to stdout)\n  3. `readlinkf_* \"\u003cpath\u003e\"` (output to stdout, not recommended)\n\nNote: Usage 1 and 2 use subshells and therefore have no side effects. It does\nnot change the current directory and any variables. Usage 3 has side effects.\n\nThe maximum depth of symbolic links is 40. This value is the same as defined in Linux kernel 5.6. (See [MAXSYMLINKS](MAXSYMLINKS))\nHowever, `readlink -f` has not limitation. If you want to change, modify `max_symlinks` variable in these function.\n\n[MAXSYMLINKS]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/namei.h?h=v5.6\u0026id=7111951b8d4973bda27ff663f2cf18b663d15b48#n13\n\n### 1. readlinkf_posix\n\nThis implementation uses `cd -P` and `ls -dl`.\n\n#### How it works\n\nIt parsing the output of `ls -dl` and resolve symbolic links.\n\n```sh\nls -dl: \"%s %u %s %s %u %s %s -\u003e %s\\n\",\n  \u003cfile mode\u003e, \u003cnumber of links\u003e, \u003cowner name\u003e, \u003cgroup name\u003e,\n  \u003csize\u003e, \u003cdate and time\u003e, \u003cpathname of link\u003e, \u003ccontents of link\u003e\n```\n\nThe format of `ls -dl` is specified in [POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html).\n\n\u003e If the file is a symbolic link and the -L option is not specified, this\n\u003e information shall be about the link itself and the `\u003cpathname\u003e` field shall be of the form:\n\u003e\n\u003e `\"%s -\u003e %s\", \u003cpathname of link\u003e, \u003ccontents of link\u003e`\n\n### 2. readlinkf_readlink\n\nThis implementation uses `cd -P` and `readlink` (without `-f`).\n\nNote: Probably fast than `readlinkf_posix`, but `readlink` is not POSIX compliant.\nIt may not be installed in some environments.\n\n## Limitation\n\n`readlinkf` cannot handle filenames that end with a newline.\nIt is very rare case, therefore I chose performance and code simplicity.\n\n## About the test\n\n[![Test Results](https://img.shields.io/cirrus/github/ko1nksm/readlinkf/master?label=Test%20results\u0026style=for-the-badge)](https://cirrus-ci.com/github/ko1nksm/readlinkf/master)\n\nTested with `ash` (busybox), `bosh`, `bash`, `dash`, `ksh`, `mksh`, `posh`, `yash`, `zsh` on Debian.\nAnd tested on macOS, FreeBSD, Cygwin, Msys2 and Git BASH.\nThe tests are compared with the result of GNU `readlink -f` (`greadlink`) command.\n\nIf you want to test yourself, use `test.sh` script.\nRoot privilege is required for edge case test around the root directory.\nTherefore using Docker by default for safely create files on the root directory.\n\n```sh\n./test.sh [SHELL (default:sh)] [Dockerfile] [DOCKER-TAG (default: latest)]\n```\n\nNote: The `readlink` built into busybox is not compatible with `readlink` of GNU coreutils.\n\n```sh\n./test.sh ash dockerfiles/alpine 3.11 # will fails\n```\n\nIf you want to test without Docker, set `ALLOW_CREATION_TO_THE_ROOT_DIRECTORY`\nenvironment variable. Check `test.sh` script for what it do before running it.\n\n```sh\nsudo ALLOW_CREATION_TO_THE_ROOT_DIRECTORY=1 ./test.sh\n```\n\n## Changelog\n\n- v1.0.0: 2020-05-13 Short code version\n- v1.1.0: 2020-06-20: Friendly version\n\n## License\n\nCreative Commons Zero v1.0 Universal.\nFeel free to modified or embed in your script.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fko1nksm%2Freadlinkf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fko1nksm%2Freadlinkf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fko1nksm%2Freadlinkf/lists"}