Why can’t watch run my shell function?

0
2
Asked By MellowPine42 On

I have a command that finds files changed within the last minute, sorts them by modification time, and displays the ten most recent results:

```sh
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 and run with `watch`, but I wanted to define it as a shell 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
```

The function runs normally when called directly in my shell, but `watch` reports that `what-changed` cannot be found. Why can't `watch` see the function, and what is the best way to run this repeatedly?

4 Answers

Answered By VividCedar19 On

You can export the function and explicitly tell `watch` to use Bash:

```bash
export -f what-changed
watch bash -c what-changed
```

The important part is `bash -c`; plain `watch what-changed` uses `sh`, which generally does not import or understand exported Bash functions. This also needs to be done in the same shell where the function was defined.

Answered By CopperLynx7 On

A shell function exists only inside the current shell process. `watch` starts another process and normally runs the command through `/bin/sh`, so it cannot see functions, aliases, or other definitions that only exist in your interactive Bash session. Keeping the command in an executable script is the simplest and most portable solution.

Answered By AmberKite53 On

If you want to pass the complete pipeline directly to `watch`, quote the entire command so the pipeline is interpreted by the shell started by `watch`:

```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"
```

However, with formatting strings and nested quotes, a small script is usually easier to read and less error-prone.

Answered By QuietOrbit6 On

Another option is to avoid `watch` and run the command in a loop:

```bash
while true; do
clear
what-changed
sleep 5
done
```

That runs in the current shell, so the function is available, and it is easy to adjust the delay or add other commands. You can also use `while date; do` if displaying the current time is useful.

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.