How to run a shell script when a file or directory changes?
Use inotify-tools.
The linked Github page has a number of examples; here is one of them.
#!/bin/sh
cwd=$(pwd)
inotifywait -mr \
--timefmt '%d/%m/%y %H:%M' --format '%T %w %f' \
-e close_write /tmp/test |
while read -r date time dir file; do
changed_abs=${dir}${file}
changed_rel=${changed_abs#"$cwd"/}
rsync --progress --relative -vrae 'ssh -p 22' "$changed_rel" \
usernam@example.com:/backup/root/dir && \
echo "At ${time} on ${date}, file $changed_abs was backed up via rsync" >&2
done
How to execute a shell script when a file changes?
First of all, the [[1617030570: command not found
error is caused by a missing space after the [[
(Not shown in question)
Secondly, you'll always run ./targetscript.sh
on the first iteration since LTIME
isn't set. Therefore the "$ATIME" != "$LTIME"
will fail, and the sh
script will be executed.
Consider setting $LTIME
before the while-loop:
#!/bin/bash
LTIME=$(stat -c %Z /private/tmp/jq/tst.txt)
while true
do
ATIME=$(stat -c %Z /private/tmp/jq/tst.txt)
if [[ "$ATIME" != "$LTIME" ]]; then
echo "RUN COMMNAD"
./targetscript.sh
LTIME=$ATIME
fi
sleep 2
done
monitor a folder tree for changes and run a script when a file is created - linux
inotify
is being around for a while, It's stable and is part of main stream of many distros.
How to install:
on Ubuntu:
sudo apt-get install inotify-tools
on Centos/RHEL (from EPEL repo):
yum --enablerepo epel install inotify-tools
How to use:
inotifywait -re create /tmp/test1/ && echo "Change detected"
Once you create a file echo "change detected"
will be triggered which could be just about anything.
The output you get:
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
/tmp/test1/test2/test3/ CREATE file
Change detected
PS. -r
for recursive -e create
to detect new files.
Shell Script - opening files from a different directory
Here is a code to open the bar directory with nautilus (ubuntu's explorer):
#!/bin/bash
path='/home/your_user_name/foo'
nautilus $path/bar/
Rules:
- Use absolute path:
/home/your_user_name/
, not~/
nor$HOME
. - Bash doesn't like spaces:
path='~/Datasets/foo'
, and notpath = '~/Datasets/foo'
How to change current directory via shell script and execute command there?
This is very nearly a duplicate of Change the current directory from a Bash script, and the answer is very similar -- the only difference being the appending of the command you want to run.
Don't use a script at all; instead, in your ~/.bashrc
or similar, define a function:
runInMyDir() {
cd ~/my-dir || return
runall
}
...to define a command runInMyDir
. (If you want runall
to happen in the background, add a &
at the end of that line).
If you do want a script, that script needs to be source
d rather than executed out-of-process -- when a program is executed as an executable external to the shell, it has already been split off from the original shell before it starts, so it has no opportunity to change that shell's behavior. Thus, if you created a file named runInMyDir
with the commands cd ~/my-dir || return
and runall
, you would need to run source runInMyDir
rather than just runInMyDir
to invoke it.
Bash script to check if a new file has been created on a directory after run a command
Thanks to informative comments, I've just realized that I've missed the basics of bash script but finally made that work. I'll leave my solution here as an answer for those who struggle like me.:
WATCH_DIR=./tmp
FILES_BEFORE=$(ls $WATCH_DIR)
echo >$WATCH_DIR/filename
FILES_AFTER=$(ls $WATCH_DIR)
if diff <(echo "$FILES_AFTER") <(echo "$FILES_BEFORE")
then
echo "No changes"
else
echo "Changes"
fi
It outputs "Changes" on the first run and "No Changes" for the other unless you delete the newly added documents.
How to run a .sh-script from any path in a terminal?
One option is simply to type the path to the script:
~/Desktop/script
This works fine, but gets a bit unwieldy.
This is what the PATH
environment variable is for. And it is what $HOME/bin
is for.
- Create yourself a directory
$HOME/bin
. Put all your executable scripts in it (make them executable withchmod +x script
if need be††). This way, there's one place to look for the scripts you want to run. - Add
$HOME/bin
to yourPATH
. I put mine at the front:PATH="$HOME/bin:$PATH
, but you could put it at the back if you prefer. - Update your
.profile
or.bash_profile
(or possibly.bashrc
) file to setPATH
. Beware of a continually growing PATH, though.
As tripleee noted, once the command is installed in a directory on PATH
, you no longer type ./script
, but just script
. This is exactly like you type ls
and not /bin/ls
, etc. Once the program is installed in a directory on your PATH
, it is (for many purposes) indistinguishable from a system-provided command.
I have about 500 scripts and programs in my $HOME/bin
directory.
Note that this doesn't require any special privileges. If you have administrator access to your machine and you think other users might find your commands useful, then you could install the scripts/programs in one of the system-provided directories on your PATH
. However, it is usually best not to add programs to any of:
/bin
/usr/bin
/sbin
/usr/sbin
There is often/usually /usr/local/bin
which is a suitable place for widely used commands not provided by the system.
†† It would be better to use chmod a+x,go-w script
; your scripts should not be writable by other people. You could even simply use chmod 555 script
or chmod 755 script
. I tend to keep my scripts non-writable. That way, I have to go through a formal change process with the version control system. It means there's less danger of uncontrolled changes.
Executing shell script without changing its environment
Please try the following:
( cd dir1; ./script1 )
( cd dir2; ./script2 )
( cd dir3; ./script3 )
Note that () are needed to save/restore you master script current directory.
Related Topics
How to Compare Two Strings in Dot Separated Version Format in Bash
How to Kill a Child Process After a Given Timeout in Bash
Using Awk to Count the Number of Occurrences of a Word in a Column
Are There Any Standard Exit Status Codes in Linux
Bash Script Prints "Command Not Found" on Empty Lines
Error:13 - Permission Denied Android Studio
How to Grep For Contents After Pattern
Redirect All Output to File in Bash
Sort a List With Lowercase First
Passing Variable to Bash Script in a Jenkins Pipeline Job
Why Should Eval Be Avoided in Bash, and What Should I Use Instead
What's the Best Way to Send a Signal to All Members of a Process Group
Remove a Specific Character Using Awk or Sed
How to Keep Environment Variables When Using Sudo
How to Set the Environmental Variable Ld_Library_Path in Linux
How to Get the Bssid of Currently Connected Network Through Bash