Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Post History

66%
+2 −0
Q&A Higher-order functions in Bash?

Say I have some Bash function my-func, that expects a filename and does some processing on the corresponding file. For demonstration purposes, my-func() { cat "$1"; } If I want to apply that fu...

1 answer  ·  posted 8mo ago by Karl Knechtel‭  ·  last activity 8mo ago by Kamil Maciorowski‭

#4: Question reopened by user avatar Canina‭ · 2023-09-23T11:16:31Z (8 months ago)
#3: Post edited by user avatar Karl Knechtel‭ · 2023-09-23T10:13:33Z (8 months ago)
Fix example for the starting point; fix attempt to match and explain issues with this attempt
  • Say I have some Bash function `my-func`, that expects a filename and does some processing on the corresponding file. For demonstration purposes,
  • ```
  • my-func() { cat "$1"; }
  • ```
  • If I want to apply that function to all the text files in the current directory, I eventually figured out that I can do:
  • ```
  • export -f my-func
  • find . -name '*.txt' -print0 | xargs -0 bash -c 'my-func "$@"' _
  • ```
  • Now suppose I want to generalize this process. I want to make another function, where I can pass `my-func` (or some other function name, or command, or alias - the key feature is that *this will expect only one argument*, a filename forwarded from `xargs`) followed by the arguments that `find` should use to choose the files to process.
  • That is, I'd like to be able to define `apply-to-files`, such that I can call e.g. `apply-to-files my-func . -name '*.txt'` and have it do the right thing (in this case, `cat` each file found by `find . -name '*.txt'`).
  • What does that look like? My first thought is
  • ```
  • apply-to-files() {
  • find "${@:2}" -print0 | xargs -0 bash -c '$1 "$@"' _
  • }
  • ```
  • but that doesn't seem right. I need a way to disambiguate that the `$1` refers to the arguments of `apply-to-files`, but the second `$@` refers to the single-element list of arguments passed to the worker function (named in `$1`, invoked by `xargs`). I'm also getting lost in the quoting by this point.
  • Say I have some Bash function `my-func`, that expects a filename and does some processing on the corresponding file. For demonstration purposes,
  • ```
  • my-func() { cat "$1"; }
  • ```
  • If I want to apply that function to all the text files in the current directory, I eventually figured out that I can do:
  • ```
  • export -f my-func
  • find . -name '*.txt' -print0 | xargs -0 -I{} bash -c 'my-func "{}"' _
  • ```
  • Now suppose I want to generalize this process. I want to make another function, where I can pass `my-func` (or some other function name, or command, or alias - the key feature is that *this will expect only one argument*, a filename forwarded from `xargs`) followed by the arguments that `find` should use to choose the files to process.
  • That is, I'd like to be able to define `apply-to-files`, such that I can call e.g. `apply-to-files my-func . -name '*.txt'` and have it do the right thing (in this case, `cat` each file found by `find . -name '*.txt'`).
  • What does that look like? My first thought is
  • ```
  • apply-to-files() {
  • find "${@:2}" -print0 | xargs -0 -I{} bash -c '$1 "{}"' _
  • }
  • ```
  • but that doesn't seem right. I'm getting lost in the quoting, and I'm confused about which arguments are coming from where. And indeed, it doesn't seem to work; it appears to be treating the filenames from `find` as the executable name to run, causing a bunch of "Permission denied" errors. Finally, this setup is assuming that the named operation will be a Bash function; I'd prefer if it could work transparently with (executables, aliases, shell builtins, ...) as well.
#2: Question closed by user avatar Karl Knechtel‭ · 2023-09-23T09:54:54Z (8 months ago)
#1: Initial revision by user avatar Karl Knechtel‭ · 2023-09-23T09:36:44Z (8 months ago)
Higher-order functions in Bash?
Say I have some Bash function `my-func`, that expects a filename and does some processing on the corresponding file. For demonstration purposes,
```
my-func() { cat "$1"; }
```

If I want to apply that function to all the text files in the current directory, I eventually figured out that I can do:
```
export -f my-func
find . -name '*.txt' -print0 | xargs -0 bash -c 'my-func "$@"' _
```
Now suppose I want to generalize this process. I want to make another function, where I can pass `my-func` (or some other function name, or command, or alias - the key feature is that *this will expect only one argument*, a filename forwarded from `xargs`) followed by the arguments that `find` should use to choose the files to process.

That is, I'd like to be able to define `apply-to-files`, such that I can call e.g. `apply-to-files my-func . -name '*.txt'` and have it do the right thing (in this case, `cat` each file found by `find . -name '*.txt'`).

What does that look like? My first thought is
```
apply-to-files() {
    find "${@:2}" -print0 | xargs -0 bash -c '$1 "$@"' _
}
```
but that doesn't seem right. I need a way to disambiguate that the `$1` refers to the arguments of `apply-to-files`, but the second `$@` refers to the single-element list of arguments passed to the worker function (named in `$1`, invoked by `xargs`). I'm also getting lost in the quoting by this point.