Why can’t watch run my Bash function?

0
6
Asked By MellowCedar42 On

I have a command that lists the ten most recently changed files, excluding a couple of directories:

```bash
find -not ( -path './snap/firefox/common' -prune ) -not ( -path './.cache' -prune ) -type f -mmin -1 -printf "%C+ %pn" | sort -n | tail -10
```

It works when placed in a script, so I can run it with `watch last_change` and even create an alias for that. However, when I define the command as a Bash function instead:

```bash
function what-changed() {
find -not ( -path './snap/firefox/common' -prune ) -not ( -path './.cache' -prune ) -type f -mmin -1 -printf "%C+ %pn" | sort -n | tail -10
}

watch what-changed
```

`watch` reports that it cannot find `what-changed`, even though the function runs normally when called directly in my shell. Why is the function unavailable to `watch`, and what is the best way to run this command repeatedly?

5 Answers

Answered By CopperLynx88 On

Exporting a function with `export -f what-changed` can make it available to child Bash processes, but it will not reliably solve this particular case because `watch` commonly uses `/bin/sh`, not Bash. A Bash function is not a standalone executable, and `/bin/sh` generally cannot import Bash’s exported-function format. A script or a quoted command is more portable.

Answered By SageWindow53 On

If you want to avoid the quoting mess, use a loop instead of `watch`:

```bash
while true; do
clear
find -not ( -path './snap/firefox/common' -prune ) -not ( -path './.cache' -prune ) -type f -mmin -1 -printf '%C+ %pn' | sort -n | tail -10
sleep 5
done
```

This runs directly in your current shell, so functions work normally. You can also use `while date; do ...; sleep 5; done` if you want each refresh to show the current time.

Answered By NimbleHarbor19 On

You can also pass the entire pipeline to `watch` as one quoted command, for example:

```bash
watch "find -not ( -path './snap/firefox/common' -prune ) -not ( -path './.cache' -prune ) -type f -mmin -1 -printf '%C+ %p\n' | sort -n | tail -10"
```

Quoting the whole command keeps the pipe characters from being interpreted by your interactive shell. The inner `printf` quotes need to be adjusted or escaped so they survive until the command is evaluated by `watch`.

Answered By QuartzPilot7 On

A function normally exists only inside the current shell process. `watch` starts a separate command, usually by invoking `sh -c`, so it cannot see functions, aliases, or other definitions that only exist in your interactive Bash session. The simplest solution is to keep the command in an executable script and run that with `watch`.

Answered By BrightMango26 On

A file-monitoring tool such as `inotifywatch` is another option if the goal is to react to filesystem events rather than periodically refresh a listing. It is useful for event tracking, but it does not produce exactly the same continuously refreshed view as `watch`, so a loop or script is probably a better match here.

Related Questions

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.