I can not understand why this little script with a loop processes only one file.
At boot in /etc/rc.local i wrote:
/usr/local/bin/./myscript &
This is myscript:
#!/bin/bash
while inotifywait -e create /HOTFOLDER/ ; do
for fullname in /HOTFOLDER/*.xlsx; do
if ! [ -d "$fullname" ]; then
send=/HOTFOLDER/$(date +'SEND-%F')
sleep 10s
mkdir -p $send
mv -- "$fullname" $send
fi
done
done
I have try also the option -m in inotifywait, but same problem:
I know nothing about inotifywait but it looks to me like you are using it wrong.
Try something like this:
inotifywait -m -e create /HOTFOLDER/ 2>/dev/null | while read folder event file
do
if [[ "$event" =~ CREATE ]]
then
fullpath="$folder/$file"
# process fullpath here
fi
done
In bash everything inside that loop will be in a subshell and none of your variables will survive the loop.
Andrew
Edit: Just realised the redirect is not necessary:
inotifywait -m -q -e create /HOTFOLDER/ | while read folder event file
do
if [[ "$event" =~ CREATE ]]
then
fullpath="$folder/$file"
# process fullpath here
fi
done
Thnk you for your answer. after I will try your suggestion
the problem with myscript:
If in the HOTFOLDER there are 10 .xlsx files and then I copy a new one, the loop works all file to the end.
If there is no file inside the HOTFOLDER and then I copy 10.xlsx, the loop processes only one
Not seeing any reason in the script for the behaviour you describe, I think we need more context info. Please post the output of the script run with the -x option set, and also a directory listing from within every loop.
I have copied in the HOTFOLDER 1.xlsx 2.xlsx 3.xlsx 4.xlsx
as you can see, only the 4.xlsx number was processed and the others remained in the HOTFOLDER
after that I copied the 4.xlsx number back into the HOTFOLDER and now it has processed all the xlsx files present.
I highlight you in bold inotifywait waiting to receive input
this is the output of $:bash -x myscript.sh
+ inotifywait -e create /HOTFOLDER/
Setting up watches.
Watches established. (start of myscript)
+ for fullname in '/HOTFOLDER/*.xlsx'
+ '[' -d /HOTFOLDER/4.xlsx ']'
++ date +SEND-%F
+ send=/HOTFOLDER/SEND-2018-04-06
+ sleep 10s
+ mkdir -p /HOTFOLDER/SEND-2018-04-06
+ mv -- /HOTFOLDER/4.xlsx /HOTFOLDER/SEND-2018-04-06
+ inotifywait -e create /HOTFOLDER/
Setting up watches.
Watches established. (after copy 1-2-3-4.xlsx, as you can see it only processes number 4)
+ for fullname in '/HOTFOLDER/*.xlsx'
+ '[' -d /HOTFOLDER/1.xlsx ']'
++ date +SEND-%F
+ send=/HOTFOLDER/SEND-2018-04-06
+ sleep 10s
+ mkdir -p /HOTFOLDER/SEND-2018-04-06
+ mv -- /HOTFOLDER/1.xlsx /HOTFOLDER/SEND-2018-04-06
+ for fullname in '/HOTFOLDER/*.xlsx'
+ '[' -d /HOTFOLDER/2.xlsx ']'
++ date +SEND-%F
+ send=/HOTFOLDER/SEND-2018-04-06
+ sleep 10s
+ mkdir -p /HOTFOLDER/SEND-2018-04-06
+ mv -- /HOTFOLDER/2.xlsx /HOTFOLDER/SEND-2018-04-06
+ for fullname in '/HOTFOLDER/*.xlsx'
+ '[' -d /HOTFOLDER/3.xlsx ']'
++ date +SEND-%F
+ send=/HOTFOLDER/SEND-2018-04-06
+ sleep 10s
+ mkdir -p /HOTFOLDER/SEND-2018-04-06
+ mv -- /HOTFOLDER/3.xlsx /HOTFOLDER/SEND-2018-04-06
+ for fullname in '/HOTFOLDER/*.xlsx'
+ '[' -d /HOTFOLDER/4.xlsx ']'
++ date +SEND-%F
+ send=/HOTFOLDER/SEND-2018-04-06
+ sleep 10s
+ mkdir -p /HOTFOLDER/SEND-2018-04-06
+ mv -- /HOTFOLDER/4.xlsx /HOTFOLDER/SEND-2018-04-06
+ inotifywait -e create /HOTFOLDER/
Setting up watches.
Watches established. (after copy 4.xlsx again, as you can see it processes all xlsx present in HOTFOLDER)
Where is the directory listing as requested? Did you copy all the files in one go, or one by one? By the way, why don't you mv all .xlsx files in one go?
It is because of the way you were using inotifywait .
inotifywait -e create /some/dir
will wait for the create event in /some/dir, report that event and exit.
You copy 10 files into that directory and only the first is processed because the script is finished (or at least the wildcard *.xlsx is expanded) before the second file is added.
inotifywait -m -e create /some/dir | while read dir event file
will run the loop for every file added to the directory /some/dir and will process the files one-at-a-time.
I do not understand what you mean by directory list.
I copy all the file in one go
the command mv all .xlsx files in one go or not,
move files at once or not? I need it to be one by one.
Yes, but shouldn't the for fullname in /HOTFOLDER/*.xlsx then run across ALL files present? Or do you think it's a race / timing problem? Why, then, would the 4th (i.e. the last) file be treated only?
Somehow by the way pasaico is copying the files the fourth file is the first to be created. As soon as it is created inotifywait exits and there is a full ten seconds before it is run again. I imagine the wildcard expansion is faster than the copy which is why only one file is seen. When I tested the code 1.xlsx was copied.
Original script (modified for testing by me):
#!/bin/bash
HOTFOLDER=$PWD/HOTFOLDER
while inotifywait -e create ${HOTFOLDER} ; do
for fullname in ${HOTFOLDER}/*.xlsx; do
if ! [ -d "$fullname" ]; then
send=${HOTFOLDER}/$(date +'SEND-%F')
sleep 10s
mkdir -p $send
mv -- "$fullname" $send
fi
done
done
If we put that sleep statement between the while and for statements you give the copy time to catch up. Try it.
This is the solution I proposed (now properly coded):
#!/bin/bash
HOTFOLDER=$PWD/HOTFOLDER2
inotifywait -q -m -e create ${HOTFOLDER} | while read folder event file
do
if [[ "$event" =~ ^CREATE$ ]] && [[ "${file}" =~ \.xlsx$ ]]
then
fullpath="$folder/$file"
send=${HOTFOLDER}/$(date +'SEND-%F')
mkdir -p "${send}" && mv "${fullpath}" "${send}"
fi
done
Now, every time a file is copied or otherwise created the while loop is run. I am checking for a CREATE rather than a CREATE,ISDIR and the file has the correct extension.
thank you very much your suggestions have been very useful,
I would like to add the function to check the email from a text file.
If the variable $mail is present, togheter other event (CREATE and .xlsx) proceed with Echo "OK"
otherwise with echo "ERROR"
This way it does not work, I do not understand much about expression and operators
Presumably, going back to your original script, you want to move the file and email confirmation if the email address(es) exist. What happens if there is no email address? Move anyway? Or is that an error?
if [[ "$event" =~ ^CREATE$ ]] && [[ "${file}" =~ \.xlsx$ ]]
then
echo "do the copy"
mail=$(awk -F ',' -v var="${file%.*}" '$1==var {print $2,$3}' ${addr})
if [[ -n "$mail" ]]
then
echo "Can send email"
else
echo "ERROR cannot send email"
fi
else
echo "do nothing"
fi
if [[ "$event" =~ ^CREATE$ ]] && [[ "${file}" =~ \.xlsx$ ]] && [[ -n "$mail" ]]
then
echo "OK"
else
echo "ERROR"
fi