3

If I have a bash script which is stored in a folder, is it possible to have it running on folder opening?

First example

Suppose I have the script s in the shared folder (for example on Dropbox) foo and whenever a user types

cd /path/to/foo

I want to display a message, let's say Hello, visitor!. How could I do that (if I can)?

I've already seen this question but I found no examples about what it is said in the answers.


If that's not achievable in a simple way, is it possible for the same script to run upon detecting folder content changes or do I need a second script to check that and then run the former?

Second example

Same script s located in the same shared foo folder. If I do something like

touch test.txt

while in the foo folder, I'd like to have another message displayed, let's say You have created a new file! or rename the file accordingly to a standard for that folder.


With this configuration I have to make sure that whoever enters that folder triggers the script but I'm not able to redefine any builtin function nor modify bash files.

Community
  • 1
  • 1
  • possible duplicate of [How to run a bash script automatically on going to a directory?](http://stackoverflow.com/questions/5594314/how-to-run-a-bash-script-automatically-on-going-to-a-directory) – Zsolt Botykai Dec 18 '11 at 18:57
  • Re: edit; if anything browsed on drop-box had the capability of running arbitrary code, I'd consider that a wide, gaping security hole. No, in principle that isn't (supposed to be) possible. – sehe Dec 18 '11 at 21:15

2 Answers2

3

Another approach would be, adding something like this to .bashrc:

export CURPROMPTWD="$PWD"
export PROMPT_COMMAND=detect_dir_change

function detect_dir_change()
{
    local newcwd=$(realpath "$PWD")
    if [[ "$CURPROMPTWD" != "$newcwd" ]]
    then
        CURPROMPTWD="$newcwd"

        #### EDITED FOR COMMENT ####
        if [[ "$newcmd" == "/some/specific/path" ]]; then
            ./run_welcome.sh
        fi
    fi
}

Note that I used realpath which may not be available on your system. It was intended to avoid detecting changed directories from "~" to "/home/user" to "../user" etc.

The sample uses a simple detection to detect when the user changes to a Git worktree root and uses Git itself to display the status for that tree.

Detecting change:

You could tweak it using find. I recommend using some limiters (-maxdepth and -mmin shown below) to prevent this from becoming a resource drain. I'm sure there will be much more performant options when using inotify (but I'm not sure whether they are easily accessed from bash).

export CURPROMPTWD="$PWD"
export PROMPT_COMMAND=detect_dir_change
export CURPROMPTCHANGEID=""

function detect_dir_change()
{
    local newcwd=$(realpath "$PWD")
    if [[ "$CURPROMPTWD" != "$newcwd" ]]
    then
        CURPROMPTWD="$newcwd"
        if [ -d .git/ ]; then
            echo "Welcome into you git working tree at $newcwd"
            git status
        fi
    fi

    # due to 
    # * -maxdepth 3, changes lower than 3 levels deep below the working
    #   directory won't be seen
    # * -mmin -10, changes made longer than 10 minutes ago won't be seen; this
    #   also implies that being idle in a workdir for over 10 minutes will be
    #   detected as a 'modified working directory' (for the simple reason that
    #   is has no changeid in that case and it will compare as _unequal_ to the
    #   last-seen changeid)
    #
    # Feel free to drop both -maxdepth or -mmin if that's not
    # appropriate/necessary for your use case
    #
    # Consider adding '-type f' to only take modifications to files into
    # account. 
    # --> However, in that case, you'd probably want to watch -cmin _as well
    #     as_ -mmin (since new files won't be seens as recently modified :))
    local changeid=$(find -maxdepth 3 -mmin -10 -printf '%T+\t%i\0' | sort -z | xargs -0 -n1 | tail -1)
    if [[ "$CURPROMPTCHANGEID" != "$changeid" ]]
    then
        CURPROMPTCHANGEID="$changeid"
        echo Run some update due to recent changes
    fi
}
sehe
  • 374,641
  • 47
  • 450
  • 633
  • I want to detect a _specific_ accessed folder, so I should substitute `$newcwd` with a fixed one. But still, this would be tied to a specific machine. Can I make it independent from this? –  Dec 18 '11 at 19:52
  • @MarcelloMassaro: erm... sure? See `#### EDITED FOR COMMENT ####`. About _`tied to a specific machine`_ I'm completely lost. Nothing I did was tied to a machine. It was tied to a .bashrc only. Feel free to source it from whatever script you have running on all systems that interest you :) – sehe Dec 18 '11 at 19:59
  • sorry about being poorly clear, I've updated the examples to express myself better. :P But I didn't get the `#### EDITED FOR COMMENT ####` thing... –  Dec 18 '11 at 20:02
1

This probably isn't a good idea, but yes, you can do what you describe. To the user's .bashrc, you can add this:

function cd ()
  { builtin cd "$@" ; if [[ $PWD = /path/to/foo ]] ; then ./s ; fi ; }

(Needless to say, there are lots of caveats and limitations to this. You're modifying a basic Bash behavior, which is generally not a great idea.)

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • But this would be limited to the machine where I redefine `cd`, wouldn't it? What if I want it to be independent from that? –  Dec 18 '11 at 19:09
  • @MarcelloMassaro: I don't understand what you mean. Naturally, anything you do will only affect machines that you do it on . . . – ruakh Dec 18 '11 at 19:49
  • I'm sorry for being not clear, I'll update the question with a more specific example. –  Dec 18 '11 at 19:53