Monitoring folder for file changes
Clash Royale CLAN TAG#URR8PPP
up vote
1
down vote
favorite
I'm writing a script that monitors a folder for any file creation, deletion and changing. When one of these happens, the user is notified (every 30 seconds).
Currently, I'm using for
loops to go through the files in the directory and compare them to an array of files created beforeâÂÂhand, but I cannot differentiate between new files being added and the ones that have been modified.
The code I am using is the following.
start()
files=(~/Junk/*)
while true; do
loopstart=$(date +%s)
watcher
sleep 15
done
watcher()
ls -1 ~/Junk
echo -e "n"
for f in ~/Junk/*; do
if [[ ! "$files[@]" =~ "$f" ]]; then
echo -e "n$f has been added"
else
last_modified=$(stat -c %Z "$f")
if [ $(($loopstart - $last_modified)) -le 15 ]; then
echo -e "n$f has been changed"
fi
fi
done
for f in "$files[@]"; do
if [ ! -e "$f" ]; then
echo -e "n$f has been deleted"
fi
done
files=(~/Junk/*)
start_watcher
I'm aware of inotify and other systems that will provide a solution; I just need a Bash-only solution.
shell-script filesystems
add a comment |Â
up vote
1
down vote
favorite
I'm writing a script that monitors a folder for any file creation, deletion and changing. When one of these happens, the user is notified (every 30 seconds).
Currently, I'm using for
loops to go through the files in the directory and compare them to an array of files created beforeâÂÂhand, but I cannot differentiate between new files being added and the ones that have been modified.
The code I am using is the following.
start()
files=(~/Junk/*)
while true; do
loopstart=$(date +%s)
watcher
sleep 15
done
watcher()
ls -1 ~/Junk
echo -e "n"
for f in ~/Junk/*; do
if [[ ! "$files[@]" =~ "$f" ]]; then
echo -e "n$f has been added"
else
last_modified=$(stat -c %Z "$f")
if [ $(($loopstart - $last_modified)) -le 15 ]; then
echo -e "n$f has been changed"
fi
fi
done
for f in "$files[@]"; do
if [ ! -e "$f" ]; then
echo -e "n$f has been deleted"
fi
done
files=(~/Junk/*)
start_watcher
I'm aware of inotify and other systems that will provide a solution; I just need a Bash-only solution.
shell-script filesystems
You could usestat -c %W
which is the creation time/
â Ralph Rönnquist
Oct 29 '17 at 5:37
Your test for whether a file is new might not work right.â¯â¯ Try creating a file calledcredit
, then start the watcher, then create a file calledred
and see what happens.
â G-Man
Oct 29 '17 at 5:47
2
Some alternative ideas... Instead of relying on just filenames consider incorporating inode numbers which are unique for each file. These numbers will stay with a file even if it is renamed. Retrieve inode number withstat -c %i filename
. To determine if a file's content has changed you might use checksums instead of modification times. One way to get a checksum iscksum filename
.
â B Layer
Oct 29 '17 at 8:50
What about symlinks, hardlinks, and file names beginning with a dot, can all that be ignored?
â Hauke Laging
Oct 29 '17 at 9:59
You've asked for a "bash
-only solution". Do you really intend to discountgrep
,find
, and other external tools? If not, please could you clarify why inotify-based answers are no use to you. Thanks
â roaima
Oct 29 '17 at 10:59
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I'm writing a script that monitors a folder for any file creation, deletion and changing. When one of these happens, the user is notified (every 30 seconds).
Currently, I'm using for
loops to go through the files in the directory and compare them to an array of files created beforeâÂÂhand, but I cannot differentiate between new files being added and the ones that have been modified.
The code I am using is the following.
start()
files=(~/Junk/*)
while true; do
loopstart=$(date +%s)
watcher
sleep 15
done
watcher()
ls -1 ~/Junk
echo -e "n"
for f in ~/Junk/*; do
if [[ ! "$files[@]" =~ "$f" ]]; then
echo -e "n$f has been added"
else
last_modified=$(stat -c %Z "$f")
if [ $(($loopstart - $last_modified)) -le 15 ]; then
echo -e "n$f has been changed"
fi
fi
done
for f in "$files[@]"; do
if [ ! -e "$f" ]; then
echo -e "n$f has been deleted"
fi
done
files=(~/Junk/*)
start_watcher
I'm aware of inotify and other systems that will provide a solution; I just need a Bash-only solution.
shell-script filesystems
I'm writing a script that monitors a folder for any file creation, deletion and changing. When one of these happens, the user is notified (every 30 seconds).
Currently, I'm using for
loops to go through the files in the directory and compare them to an array of files created beforeâÂÂhand, but I cannot differentiate between new files being added and the ones that have been modified.
The code I am using is the following.
start()
files=(~/Junk/*)
while true; do
loopstart=$(date +%s)
watcher
sleep 15
done
watcher()
ls -1 ~/Junk
echo -e "n"
for f in ~/Junk/*; do
if [[ ! "$files[@]" =~ "$f" ]]; then
echo -e "n$f has been added"
else
last_modified=$(stat -c %Z "$f")
if [ $(($loopstart - $last_modified)) -le 15 ]; then
echo -e "n$f has been changed"
fi
fi
done
for f in "$files[@]"; do
if [ ! -e "$f" ]; then
echo -e "n$f has been deleted"
fi
done
files=(~/Junk/*)
start_watcher
I'm aware of inotify and other systems that will provide a solution; I just need a Bash-only solution.
shell-script filesystems
edited Oct 29 '17 at 6:27
kiamlaluno
362220
362220
asked Oct 29 '17 at 5:00
Alphala7
61
61
You could usestat -c %W
which is the creation time/
â Ralph Rönnquist
Oct 29 '17 at 5:37
Your test for whether a file is new might not work right.â¯â¯ Try creating a file calledcredit
, then start the watcher, then create a file calledred
and see what happens.
â G-Man
Oct 29 '17 at 5:47
2
Some alternative ideas... Instead of relying on just filenames consider incorporating inode numbers which are unique for each file. These numbers will stay with a file even if it is renamed. Retrieve inode number withstat -c %i filename
. To determine if a file's content has changed you might use checksums instead of modification times. One way to get a checksum iscksum filename
.
â B Layer
Oct 29 '17 at 8:50
What about symlinks, hardlinks, and file names beginning with a dot, can all that be ignored?
â Hauke Laging
Oct 29 '17 at 9:59
You've asked for a "bash
-only solution". Do you really intend to discountgrep
,find
, and other external tools? If not, please could you clarify why inotify-based answers are no use to you. Thanks
â roaima
Oct 29 '17 at 10:59
add a comment |Â
You could usestat -c %W
which is the creation time/
â Ralph Rönnquist
Oct 29 '17 at 5:37
Your test for whether a file is new might not work right.â¯â¯ Try creating a file calledcredit
, then start the watcher, then create a file calledred
and see what happens.
â G-Man
Oct 29 '17 at 5:47
2
Some alternative ideas... Instead of relying on just filenames consider incorporating inode numbers which are unique for each file. These numbers will stay with a file even if it is renamed. Retrieve inode number withstat -c %i filename
. To determine if a file's content has changed you might use checksums instead of modification times. One way to get a checksum iscksum filename
.
â B Layer
Oct 29 '17 at 8:50
What about symlinks, hardlinks, and file names beginning with a dot, can all that be ignored?
â Hauke Laging
Oct 29 '17 at 9:59
You've asked for a "bash
-only solution". Do you really intend to discountgrep
,find
, and other external tools? If not, please could you clarify why inotify-based answers are no use to you. Thanks
â roaima
Oct 29 '17 at 10:59
You could use
stat -c %W
which is the creation time/â Ralph Rönnquist
Oct 29 '17 at 5:37
You could use
stat -c %W
which is the creation time/â Ralph Rönnquist
Oct 29 '17 at 5:37
Your test for whether a file is new might not work right.â¯â¯ Try creating a file called
credit
, then start the watcher, then create a file called red
and see what happens.â G-Man
Oct 29 '17 at 5:47
Your test for whether a file is new might not work right.â¯â¯ Try creating a file called
credit
, then start the watcher, then create a file called red
and see what happens.â G-Man
Oct 29 '17 at 5:47
2
2
Some alternative ideas... Instead of relying on just filenames consider incorporating inode numbers which are unique for each file. These numbers will stay with a file even if it is renamed. Retrieve inode number with
stat -c %i filename
. To determine if a file's content has changed you might use checksums instead of modification times. One way to get a checksum is cksum filename
.â B Layer
Oct 29 '17 at 8:50
Some alternative ideas... Instead of relying on just filenames consider incorporating inode numbers which are unique for each file. These numbers will stay with a file even if it is renamed. Retrieve inode number with
stat -c %i filename
. To determine if a file's content has changed you might use checksums instead of modification times. One way to get a checksum is cksum filename
.â B Layer
Oct 29 '17 at 8:50
What about symlinks, hardlinks, and file names beginning with a dot, can all that be ignored?
â Hauke Laging
Oct 29 '17 at 9:59
What about symlinks, hardlinks, and file names beginning with a dot, can all that be ignored?
â Hauke Laging
Oct 29 '17 at 9:59
You've asked for a "
bash
-only solution". Do you really intend to discount grep
, find
, and other external tools? If not, please could you clarify why inotify-based answers are no use to you. Thanksâ roaima
Oct 29 '17 at 10:59
You've asked for a "
bash
-only solution". Do you really intend to discount grep
, find
, and other external tools? If not, please could you clarify why inotify-based answers are no use to you. Thanksâ roaima
Oct 29 '17 at 10:59
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
1
down vote
You can use the output of
find . -mindepth 1 -maxdepth 1 -type f -printf '%C@ %T@ ' -ls
which is a lot faster than calling stat
(especially several times) per file. The combination of -printf
and -ls
has a better handling of strange file names. If you can be sure such ones will not occur then you can use
-printf '%i %C@ %T@ %P'
instead.
The inode (as mentioned in the comments) identifies the object. The ctime and mtime tell you whether the file data or metadata has been written (does not tell you whether it has really changed, though). You should write these data to arrays in a
find ... | while IFS= read ctime mtime inode dummy1 ... dummy9 rest; do ...
loop.
add a comment |Â
up vote
0
down vote
The issue is the very end of the script. I'll repost your script with the correction.
change "start_watcher" to "start" since you are trying to run the start function.
add a comment |Â
up vote
0
down vote
Try to use Auditd
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security_guide/chap-system_auditing
For monitoring a directory, you need
auditctl -w /path/to/dir -p wa -k CHANGED_ON_DIR
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
You can use the output of
find . -mindepth 1 -maxdepth 1 -type f -printf '%C@ %T@ ' -ls
which is a lot faster than calling stat
(especially several times) per file. The combination of -printf
and -ls
has a better handling of strange file names. If you can be sure such ones will not occur then you can use
-printf '%i %C@ %T@ %P'
instead.
The inode (as mentioned in the comments) identifies the object. The ctime and mtime tell you whether the file data or metadata has been written (does not tell you whether it has really changed, though). You should write these data to arrays in a
find ... | while IFS= read ctime mtime inode dummy1 ... dummy9 rest; do ...
loop.
add a comment |Â
up vote
1
down vote
You can use the output of
find . -mindepth 1 -maxdepth 1 -type f -printf '%C@ %T@ ' -ls
which is a lot faster than calling stat
(especially several times) per file. The combination of -printf
and -ls
has a better handling of strange file names. If you can be sure such ones will not occur then you can use
-printf '%i %C@ %T@ %P'
instead.
The inode (as mentioned in the comments) identifies the object. The ctime and mtime tell you whether the file data or metadata has been written (does not tell you whether it has really changed, though). You should write these data to arrays in a
find ... | while IFS= read ctime mtime inode dummy1 ... dummy9 rest; do ...
loop.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
You can use the output of
find . -mindepth 1 -maxdepth 1 -type f -printf '%C@ %T@ ' -ls
which is a lot faster than calling stat
(especially several times) per file. The combination of -printf
and -ls
has a better handling of strange file names. If you can be sure such ones will not occur then you can use
-printf '%i %C@ %T@ %P'
instead.
The inode (as mentioned in the comments) identifies the object. The ctime and mtime tell you whether the file data or metadata has been written (does not tell you whether it has really changed, though). You should write these data to arrays in a
find ... | while IFS= read ctime mtime inode dummy1 ... dummy9 rest; do ...
loop.
You can use the output of
find . -mindepth 1 -maxdepth 1 -type f -printf '%C@ %T@ ' -ls
which is a lot faster than calling stat
(especially several times) per file. The combination of -printf
and -ls
has a better handling of strange file names. If you can be sure such ones will not occur then you can use
-printf '%i %C@ %T@ %P'
instead.
The inode (as mentioned in the comments) identifies the object. The ctime and mtime tell you whether the file data or metadata has been written (does not tell you whether it has really changed, though). You should write these data to arrays in a
find ... | while IFS= read ctime mtime inode dummy1 ... dummy9 rest; do ...
loop.
answered Oct 29 '17 at 10:49
Hauke Laging
53.6k1282130
53.6k1282130
add a comment |Â
add a comment |Â
up vote
0
down vote
The issue is the very end of the script. I'll repost your script with the correction.
change "start_watcher" to "start" since you are trying to run the start function.
add a comment |Â
up vote
0
down vote
The issue is the very end of the script. I'll repost your script with the correction.
change "start_watcher" to "start" since you are trying to run the start function.
add a comment |Â
up vote
0
down vote
up vote
0
down vote
The issue is the very end of the script. I'll repost your script with the correction.
change "start_watcher" to "start" since you are trying to run the start function.
The issue is the very end of the script. I'll repost your script with the correction.
change "start_watcher" to "start" since you are trying to run the start function.
answered Feb 12 at 19:03
Nkiruka Christian
1
1
add a comment |Â
add a comment |Â
up vote
0
down vote
Try to use Auditd
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security_guide/chap-system_auditing
For monitoring a directory, you need
auditctl -w /path/to/dir -p wa -k CHANGED_ON_DIR
add a comment |Â
up vote
0
down vote
Try to use Auditd
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security_guide/chap-system_auditing
For monitoring a directory, you need
auditctl -w /path/to/dir -p wa -k CHANGED_ON_DIR
add a comment |Â
up vote
0
down vote
up vote
0
down vote
Try to use Auditd
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security_guide/chap-system_auditing
For monitoring a directory, you need
auditctl -w /path/to/dir -p wa -k CHANGED_ON_DIR
Try to use Auditd
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security_guide/chap-system_auditing
For monitoring a directory, you need
auditctl -w /path/to/dir -p wa -k CHANGED_ON_DIR
answered Feb 12 at 19:08
CorTheZ
1272
1272
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f401155%2fmonitoring-folder-for-file-changes%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
You could use
stat -c %W
which is the creation time/â Ralph Rönnquist
Oct 29 '17 at 5:37
Your test for whether a file is new might not work right.â¯â¯ Try creating a file called
credit
, then start the watcher, then create a file calledred
and see what happens.â G-Man
Oct 29 '17 at 5:47
2
Some alternative ideas... Instead of relying on just filenames consider incorporating inode numbers which are unique for each file. These numbers will stay with a file even if it is renamed. Retrieve inode number with
stat -c %i filename
. To determine if a file's content has changed you might use checksums instead of modification times. One way to get a checksum iscksum filename
.â B Layer
Oct 29 '17 at 8:50
What about symlinks, hardlinks, and file names beginning with a dot, can all that be ignored?
â Hauke Laging
Oct 29 '17 at 9:59
You've asked for a "
bash
-only solution". Do you really intend to discountgrep
,find
, and other external tools? If not, please could you clarify why inotify-based answers are no use to you. Thanksâ roaima
Oct 29 '17 at 10:59