Bash script, watch folder, execute command

后端 未结 12 1298
小鲜肉
小鲜肉 2020-12-04 08:57

I am trying to create a bash script with 2 parameters:

  • a directory
  • a command.

I want to watch the

相关标签:
12条回答
  • 2020-12-04 09:01

    probably the fastest way of doing it.. (on 1G git repo, returns under 1sec.)

    #!/bin/bash
    
    watch() {
    
        echo watching folder $1/ every $2 secs.
    
    while [[ true ]]
    do
        files=`find $1 -type f -mtime -$2s`
        if [[ $files == "" ]] ; then
            echo "nothing changed"
        else
                echo changed, $files
        fi
        sleep $2
    done
    }
    
    watch folder 3
    
    0 讨论(0)
  • 2020-12-04 09:04

    In Mac OS X, you can just control-click a folder, then click 'Folder Actions Setup'. This will allow you attach actions to a folder, i.e. scripts to run.

    OS X comes with a number of prebuilt scripts, or you can create your own.

    0 讨论(0)
  • 2020-12-04 09:07

    Here's an example of watching a folder for changes and running a the less compiler when one is updated. As a prereq you need npm and these the module onchange. The node community has a whole bunch of different watch commands (like onchange) I'm not aware of any that are compiled self-contained binaries.

    npm install less onchange -g
    

    Then you can use something like:

    onchange "./stylesheets/*.less" -- lessc main.less > main.css
    

    I prefer a BASH command over the Grunt answer I gave a while back.

    0 讨论(0)
  • 2020-12-04 09:12

    I can’t believe nobody posted this yet.

    First make sure inotify-tools are installed.

    Then use them like this:

    logOfChanges="/tmp/changes.log.csv" # Set your file name here.
    
    # Lock and load
    inotifywait -mrcq $DIR > "$logOfChanges" &
    IN_PID=$$
    
    # Do your stuff here
    ...
    
    # Kill and analyze
    kill $IN_PID
    cat "$logOfChanges" | while read entry; do
       # Split your CSV, but beware that file names may contain spaces too.
       # Just look up how to parse CSV with bash. :)
       path=... 
       event=...
       ...  # Other stuff like time stamps?
       # Depending on the event…
       case "$event" in
         SOME_EVENT) myHandlingCode path ;;
         ...
         *) myDefaultHandlingCode path ;;
    done
    

    Alternatively, using --format instead of -c on inotifywait would be an idea.

    Just man inotifywait and man inotifywatch for more infos.

    0 讨论(0)
  • 2020-12-04 09:12

    Almost 3 years later and I'd recommend this grunt based solution.

    • grunt
    • grunt-contrib-watch
    • grunt-shell

    I created a working example here https://github.com/reggi/watch-execute.

    Here's the Gruntfile.js:

    module.exports = function (grunt) {
      grunt.initConfig({
        shell: {
          run_file:{
            command: 'sh ./bash.sh',
            options: {
                stdout: true
            }
          }
        },
        watch: {
          run_file: {
            files: ["./watchme/*"],
            tasks: ["shell:run_file"]
          }
        }
      });
      grunt.loadNpmTasks('grunt-contrib-watch');
      grunt.loadNpmTasks('grunt-shell');
    };
    
    0 讨论(0)
  • 2020-12-04 09:13

    Here's a template to work with, it'll check every 120 seconds for changes in passed directory and notify on creation of directories,files,or names pipes. If you also want to run commands when something is removed then check my other answer on stackoverflow for additional looping examples.

    #!/usr/bin/env bash
    Var_dir="${1:-/tmp}"
    Var_diff_sleep="${2:-120}"
    Var_diff_opts="--suppress-common-lines"
    Func_parse_diff(){
        _added="$(grep -E '>' <<<"${@}")"
        if [ "${#_added}" != "0" ]; then
            mapfile -t _added_list <<<"${_added//> /}"
            _let _index=0
            until [ "${#_added_list[@]}" = "${_index}" ]; do
                _path_to_check="${Var_dir}/${_added_list[${_index}]}"
                if [ -f "${_path_to_check}" ]; then
                    echo "# File: ${_path_to_check}"
                elif [ -d "${_path_to_check}" ]; then
                    echo "# Directory: ${_path_to_check}"
                if [ -p "${_path_to_check}" ]; then
                    echo "# Pipe: ${_path_to_check}"
                fi
                let _index++
            done
            unset _index
        fi
    }
    Func_watch_bulk_dir(){
        _current_listing=""
        while [ -d "${Var_dir}" ]; do
            _new_listing="$(ls "${Var_dir}")"
            _diff_listing="$(diff ${Var_dec_diff_opts} <(${Var_echo} "${_current_listing}") <(${Var_echo} "${_new_listing}"))"
            if [ "${_diff_listing}" != "0" ]; then
                Func_parse_diff "${_diff_listing}"
            fi
            _current_listing="${_new_listing}"
            sleep ${Var_diff_sleep}
        done
    }
    

    Hint if you replace the echo lines above with eval <some command> for each type of action monitored for you'll be all the closer to automation of actions. And if you wish to see what the above looks like when used within a script then check out the latest script version for the project I've been working on for automation of encryption and decryption via gpg and tar.

    0 讨论(0)
提交回复
热议问题