{"id":13572355,"url":"https://github.com/sharkdp/shell-functools","last_synced_at":"2025-05-14T05:10:49.597Z","repository":{"id":54823263,"uuid":"111244031","full_name":"sharkdp/shell-functools","owner":"sharkdp","description":"Functional programming tools for the shell","archived":false,"fork":false,"pushed_at":"2024-11-22T18:55:20.000Z","size":117,"stargazers_count":1226,"open_issues_count":14,"forks_count":54,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-05-14T03:24:10.147Z","etag":null,"topics":["command-line","filesystem","functional-programming","shell","string-manipulation"],"latest_commit_sha":null,"homepage":null,"language":"Python","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/sharkdp.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},"funding":{"github":"sharkdp"}},"created_at":"2017-11-18T22:20:55.000Z","updated_at":"2025-05-11T21:13:20.000Z","dependencies_parsed_at":"2024-01-14T03:51:53.153Z","dependency_job_id":"73be6c47-c259-4304-a73a-d159279e2221","html_url":"https://github.com/sharkdp/shell-functools","commit_stats":{"total_commits":118,"total_committers":9,"mean_commits":13.11111111111111,"dds":"0.38983050847457623","last_synced_commit":"2e770edca7bd7ff90349080042d024c5df7fb449"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharkdp%2Fshell-functools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharkdp%2Fshell-functools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharkdp%2Fshell-functools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sharkdp%2Fshell-functools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sharkdp","download_url":"https://codeload.github.com/sharkdp/shell-functools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254076850,"owners_count":22010611,"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":["command-line","filesystem","functional-programming","shell","string-manipulation"],"created_at":"2024-08-01T14:01:20.939Z","updated_at":"2025-05-14T05:10:49.416Z","avatar_url":"https://github.com/sharkdp.png","language":"Python","readme":"# shell-functools\n\n[![Unit tests](https://github.com/sharkdp/shell-functools/actions/workflows/ci.yml/badge.svg)](https://github.com/sharkdp/shell-functools/actions/workflows/ci.yml)\n\n*A collection of functional programming tools for the shell.*\n\nThis project provides higher order functions like `map`, `filter`, `foldl`, `sort_by` and `take_while` as simple command-line tools.\nFollowing the UNIX philosophy, these commands are designed to be composed via pipes. A\n[large collection](#available-function-arguments) of functions such as `basename`, `replace`, `contains` or `is_dir` are provided as\narguments to these commands.\n\n## Contents\n\n* [Demo](#demo)\n* [Quick start](#quick-start)\n* [Documentation and examples](#documentation-and-examples)\n    * [Usage of `map`](#usage-of-map)\n    * [Usage of `filter`](#usage-of-filter)\n    * [Usage of `foldl`](#usage-of-foldl)\n    * [Usage of `foldl1`](#usage-of-foldl1)\n    * [Usage of `sort_by`](#usage-of-sort_by)\n    * [Chaining commands](#chaining-commands)\n    * [Lazy evaluation](#lazy-evaluation)\n    * [Working with columns](#working-with-columns)\n    * [Available function arguments](#available-function-arguments)\n\n## Demo\n\n\u003ca href=\"https://asciinema.org/a/6zsp3hEPpM7tmWHrjThl7idqh\" target=\"_blank\"\u003e\u003cimg src=\"https://asciinema.org/a/6zsp3hEPpM7tmWHrjThl7idqh.png\" width=\"600\" /\u003e\u003c/a\u003e\n\n## Quick start\n\nIf you want to try it out on your own, run:\n``` bash\npip install shell-functools\n```\n\n## Documentation and examples\n\n### Usage of `map`\n\nThe `map` command takes a [function argument](#available-function-arguments) and applies it to every line of input:\n``` bash\n\u003e ls\ndocument.txt\nfolder\nimage.jpg\n\n\u003e ls | map abspath\n/tmp/demo/document.txt\n/tmp/demo/folder\n/tmp/demo/image.jpg\n```\n\n### Usage of `filter`\n\nThe `filter` command takes a [function argument](#available-function-arguments) with a `Bool`ean return type. It applies that function to each input line and shows only those that returned `true`:\n``` bash\n\u003e find\n.\n./folder\n./folder/me.jpg\n./folder/subdirectory\n./folder/subdirectory/song.mp3\n./document.txt\n./image.jpg\n\n\u003e find | filter is_file\n./folder/me.jpg\n./folder/subdirectory/song.mp3\n./document.txt\n./image.jpg\n```\n\n### Usage of `foldl`\n\nThe `foldl` command takes a [function argument](#available-function-arguments) and an initial value. The given function must be a binary function with two arguments, like `add` or `append`. The `foldl` command then applies this function iteratively by keeping an internal accumulator:\n\nAdd up the numbers from 0 to 100:\n``` bash\n\u003e seq 100 | foldl add 0\n5050\n```\n\nMultiply the numbers from 1 to 10:\n``` bash\n\u003e seq 10 | foldl mul 1\n3628800\n```\n\nAppend the numbers from 1 to 10 in a string:\n``` bash\n\u003e seq 10 | map append \" \" | foldl append \"\"\n1 2 3 4 5 6 7 8 9 10\n```\n\n### Usage of `foldl1`\n\nThe `foldl1` command is a variant of `foldl` that uses the first input as the initial value.\nThis can be used to shorten the example above to:\n``` bash\n\u003e seq 100 | foldl1 add\n\u003e seq 10 | foldl1 mul\n\u003e seq 10 | map append \" \" | foldl1 append\n```\n\n### Usage of `sort_by`\n\nThe `sort_by` command also takes a [function argument](#available-function-arguments). In the\nbackground, it calls the function on each input line and uses the results to sort the *original input*.\nConsider the following scenario:\n``` bash\n\u003e ls\na.mp4  b.tar.gz  c.txt\n\u003e ls | map filesize\n7674860\n126138\n2214\n```\n\nWe can use the `filesize` function to sort the entries by size:\n```\n\u003e ls | sort_by filesize\nc.txt\nb.tar.gz\na.mp4\n```\n\n### Chaining commands\n\nAll of these commands can be composed by using standard UNIX pipes:\n``` bash\n\u003e find\n.\n./folder\n./folder/me.jpg\n./folder/subdirectory\n./folder/subdirectory/song.mp3\n./document.txt\n./image.jpg\n\n\u003e find | filter is_file | map basename | map append \".bak\"\nme.jpg.bak\nsong.mp3.bak\ndocument.txt.bak\nimage.jpg.bak\n```\n\n### Lazy evaluation\n\nAll commands support lazy evaluation (i.e. they consume input in a streaming way) and never perform\nunnecessary work (they exit early if the *output* pipe is closed).\n\nAs an example, suppose we want to compute the sum of all odd squares lower than 10000. Assuming we\nhave a command that prints the numbers from 1 to infinity (use `alias infinity=\"seq 999999999\"` for\nan approximation), we can write:\n``` bash\n\u003e infinity | filter odd | map pow 2 | take_while less_than 10000 | foldl1 add\n166650\n```\n\n### Working with columns\n\nThe `--column` / `-c` option can be used to apply a given function to a certain *column* in the input line (columns are separated by tabs). Column arrays can be created by using functions such as `duplicate`, `split sep` or `split_ext`:\n\n``` bash\n\u003e ls | filter is_file | map split_ext\ndocument\ttxt\nimage\tjpg\n\n\u003e ls | filter is_file | map split_ext | map -c1 to_upper\nDOCUMENT\ttxt\nIMAGE\tjpg\n\n\u003e ls | filter is_file | map split_ext | map -c1 to_upper | map join .\nDOCUMENT.txt\nIMAGE.jpg\n```\n\nHere is a more complicated example:\n``` bash\n\u003e find -name '*.jpg'\n./folder/me.jpg\n./image.jpg\n\n\u003e find -name '*.jpg' | map duplicate\n./folder/me.jpg   ./folder/me.jpg\n./image.jpg       ./image.jpg\n\n\u003e find -name '*.jpg' | map duplicate | map -c2 basename\n./folder/me.jpg   me.jpg\n./image.jpg       image.jpg\n\n\u003e find -name '*.jpg' | map duplicate | map -c2 basename | map -c2 prepend \"thumb_\"\n./folder/me.jpg\t  thumb_me.jpg\n./image.jpg       thumb_image.jpg\n\n\u003e find -name '*.jpg' | map duplicate | map -c2 basename | map -c2 prepend \"thumb_\" | map run convert\nRunning 'convert' with arguments ['./folder/me.jpg', 'thumb_me.jpg']\nRunning 'convert' with arguments ['./image.jpg', 'thumb_image.jpg']\n```\n\nGet the login shell of user `shark`:\n``` bash\n\u003e cat /etc/passwd | map split : | filter -c1 equal shark | map index 6\n/usr/bin/zsh\n```\n\n\n### Available function arguments\n\nYou can call `ft-functions`, to get an overview of all available arguments to `map`, `filter`, etc.:\n\n#### File and Directory operations ####\n```\nabspath             :: Path   → Path\ndirname             :: Path   → Path\nbasename            :: Path   → Path\nis_dir              :: Path   → Bool\nis_file             :: Path   → Bool\nis_link             :: Path   → Bool\nis_executable       :: Path   → Bool\nexists              :: Path   → Bool\nhas_ext ext         :: Path   → Bool\nstrip_ext           :: Path   → String\nreplace_ext new_ext :: Path   → Path\nsplit_ext           :: Path   → Array\n```\n#### Logical operations ####\n```\nnon_empty           :: *      → Bool\nnonempty            :: *      → Bool\n```\n#### Arithmetic operations ####\n```\nadd num             :: Int    → Int\nsub num             :: Int    → Int\nmul num             :: Int    → Int\neven                :: Int    → Bool\nodd                 :: Int    → Bool\npow num             :: Int    → Int\n```\n#### Comparison operations ####\n```\neq other            :: *      → Bool\nequal other         :: *      → Bool\nequals other        :: *      → Bool\nne other            :: *      → Bool\nnot_equal other     :: *      → Bool\nnot_equals other    :: *      → Bool\nge i                :: Int    → Bool\ngreater_equal i     :: Int    → Bool\ngreater_equals i    :: Int    → Bool\ngt i                :: Int    → Bool\ngreater i           :: Int    → Bool\ngreater_than i      :: Int    → Bool\nle i                :: Int    → Bool\nless_equal i        :: Int    → Bool\nless_equals i       :: Int    → Bool\nlt i                :: Int    → Bool\nless i              :: Int    → Bool\nless_than i         :: Int    → Bool\n```\n#### String operations ####\n```\nreverse             :: String → String\nappend suffix       :: String → String\nstrip               :: String → String\nsubstr start end    :: String → String\ntake count          :: String → String\nto_lower            :: String → String\nto_upper            :: String → String\nreplace old new     :: String → String\nprepend prefix      :: String → String\ncapitalize          :: String → String\ndrop count          :: String → String\nduplicate           :: String → Array\ncontains substring  :: String → Bool\nstarts_with pattern :: String → Bool\nstartswith pattern  :: String → Bool\nends_with pattern   :: String → Bool\nendswith pattern    :: String → Bool\nlen                 :: String → Int\nlength              :: String → Int\nformat format_str   :: *      → String\n```\n#### Array operations ####\n```\nat idx              :: Array  → String\nindex idx           :: Array  → String\njoin separator      :: Array  → String\nsplit separator     :: String → Array\nreverse             :: Array  → Array\n```\n#### Other operations ####\n```\nconst value         :: *      → *\nrun command         :: Array  → !\nid                  :: *      → *\nidentity            :: *      → *\n```\n","funding_links":["https://github.com/sponsors/sharkdp"],"categories":["Python","\u003ca name=\"scripting\"\u003e\u003c/a\u003escripting","shell"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsharkdp%2Fshell-functools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsharkdp%2Fshell-functools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsharkdp%2Fshell-functools/lists"}