I have a bash shell script using inotifywait to capture files added to a specific Dropbox folder, running a process and saving the file to another Dropbox folder. I'm running PopOS 22.04.
For some reason, inotifywait is now saying $filename is .goutputfile-xxxx and not the actual file name. In earlier testing of this process, it did not do this.
I have found a forum page about commenting out set locking in nanorc config file, but this did nothing.
Below is the opening code to the bash shell script:
#!/bin/bash
#set time and date variables
TIMENOW="$(date +"%T")"
DATENOW="$(date +"%m-%d-%Y")"
#launch the inotifywait utility formatting output to just the file name and piping it into while function to process
#file is saved to Dropbox folder from the first part of a Zapier process
inotifywait -m -e create --format %f /home/dave/Dropbox/Inbound |
while read -r filename event; do
Please let me know what config file I need to edit or code I need to use to force inotifywait to use the actual file name and not the .goutputstream-xxxx name.
I tried editing the nanorc config file by commenting out set locking option per another forum post. This did nothing.
I need some way of capturing the actual file name, even if it is in a separate variable.
Related
I have a script to automate adding movie data to my website and download the correct subtitles for them by using inotify to launch other scripts. So that it only runs on the new file I need the complete file path like "/var/www/html/movies/my movie (2020)/" and file name "my movie (2020).mp4"
I've tried different methods to get it working such as:
inotifywait -m -r --format "%e %w%f" /var/www/html/uploads/Videos/ -e create -e moved_to |
while read event fullpath; do
Above doesn't pick up any files.
inotifywait -mr --format "%w%f" /var/www/html/uploads/Videos/ -e create -e moved_to |
while read event fullpath; do
Works for movies like "Freaks (2018)" but not "Zombieland Double Tap (2019)" it becomes "ZombielandTap (2019)"
Without --format at all just completely messes up some directories:
2 fast 2 furious (2003) becomes:
/dir/22 Furious (2003)/ CREATE 2 Fast 2 Furious (2003).mp4
My exact needs for it is to grab the path to and file name (I use both separately). Upon download completion in a non monitored folder the movie is moved and renamed from whatever torrent name to the actual name in the monitored directory. The final file is all I care about having the link for.
What can I do to get the path and file name either separately so I can add them together when I need it (preferred) or full path I can break up with expressions?
You have a couple of issues. In your first attempt, you monitor the directory, but you pipe the output of inotifywait to read. The pipe is not within any loop so it is a one-shot deal. You are left monitoring the directory, but your output is no longer connected to your read loop.
Your second attempt has the same issue, but this is compounded by using --format "%w%f" that does not output the event, but then attempting to read event fullpath which since your filename contains whitespace, part of the name is read into event and the rest into fullpath.
Since you are only concerned with files added to the directory --create should be the only event you need to monitor. Your use of %w%f should be fine since you are monitoring a directory, '%w' will contain the watched directory (watched_filename) and '%f' will contain the filename (event_filename).
You are using bash, so you can use process substitution in bash to establish recursive monitoring of the directory and feed filenames to a while loop to process the changes. You must quote the resulting variables throughout the rest of your script to avoid word-splitting depending on how you use them.
You can do something similar to:
while read -r fullpath
do
echo "got '$fullpath'"
done < <(inotifywait -m -r --format '%w%f' -e create "/var/www/html/uploads/Videos/")
This will continually read the absolute path and filename into the fullpath variable. As written the watch simply echos, e.g. "got '/var/www/html/uploads/Videos/name of new file.xxx'"
Example Use/Output
With the watch set on a test directory "my dir" with spaces and creating files in that directory (also with spaces) results in, e.g.
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
got '/home/david/tmpd/my dir/my movie1 (2020).mp4'
got '/home/david/tmpd/my dir/my movie2 (2020).mp4'
got '/home/david/tmpd/my dir/my movie3 (2020).mp4'
You can use fullpath in whatever further processing you need. Give it a try and let me know if you have further questions.
When I directly do cp in shell and overwrite an already existing file, the Modify attribute in stat will go with the new timestamp. However, when I run the same command from a script it will change only Access and Change attributes, but not Modify. The file is exactly the same. Why the different behavior? In stat, Modify doesn't change if the file is the same?
Command that I'm running:
for file in $BACKUP_PATH"msghtml/messages.es.po_$deploTime"; do
filnam="$(sudo basename $file)";
sudo cp -v $file "$FEW_PATH/app/translations/"${filnam%%_*};
done
I just during the weekend decided to try out zsh and have a bit of fun with it. Unfortunately I'm an incredible newbie to shell scripting in general.
I have this folder with a file, which filename is a hash (4667e85581f80b6936f8811f0a7493c70eae4ee7) without a file-extension.
What I would like to do is copy this file to another folder and rename it to "screensaver.png".
I've tried with the following code:
#!/usr/bin/zsh
KUVVA_CACHE="$HOME/Library/Containers/com.kuvva.Kuvva-Wallpapers/Data/Library/Application Support/Kuvva"
DEST_FOLDER="/Library/Desktop Pictures/Kuvva/$USERNAME/screensaver.png"
for wallpaper in ${KUVVA_CACHE}; do
cp -f ${wallpaper} ${DEST_FOLDER}
done
This returns the following error:
cp: /Users/Morten/Library/Containers/com.kuvva.Kuvva-Wallpapers/Data/Library/Application Support/Kuvva is a directory (not copied).
And when I try to echo the $wallpaper variable instead of doing "cp" then it just echo's the folder path.
The name of the file changes every 6 hour, which is why I'm doing the for-loop. So I never know what the name of the file will be, but I know that there's always only ONE file in the folder.
Any ideas how I can manage to do this? :)
Thanks a lot!
Morten
It should work with regular filename expansion (globbing).
KUVVA_CACHE="$HOME/Library/Containers/com.kuvva.Kuvva-Wallpapers/Data/Library/Application Support/Kuvva/"
And then copy
cp -f ${KUVVA_CACHE}/* ${DEST_FOLDER}
You can add the script to your crontab so it will be run at a certain interval. Edit it using 'crontab -e' and add
30 */3 * * * /location/of/your/script
This will run it every third hour. First digit is minutes. Star indicates any. Exit the editor by pressing the escape-key, then shift+: and type wq and press enter. These vi-commands.
Don't forget to 'chmod 0755 file-name' the script so it becomes executable.
Here is the script.
#!/bin/zsh
KUVVA_CACHE="$HOME/Library/Containers/com.kuvva.Kuvva-Wallpapers/Data/Library/Application Support/Kuvva"
DEST_FOLDER="/Library/Desktop Pictures/Kuvva/$USERNAME/screensaver.png"
cp "${KUVVA_CACHE}/"* "${DEST_FOLDER}"
I am new to bash scripting and I have to create a script that will run on all computers within my group at work (so it's not just checking one computer). We have a spreadsheet that keeps certain file information, and I am working to automate the updating of that spreadsheet. I already have an existing python script that gathers the information needed and writes to the spreadsheet.
What I need is a bash script (cron job, maybe?) that is activated anytime a user deletes a file that matches a certain extension within the specified file path. The script should hold on to the file name before it is completely deleted. I don't need any other information besides the name.
Does anyone have any suggestions for where I should begin with this? I've searched a bit but not found anything useful yet.
It would be something like:
for folders and files in path:
if file ends in .txt and is being deleted:
save file name
To save the name of every file .txt deleted in some directory path or any of its subdirectories, run:
inotifywait -m -e delete --format "%w%f" -r "path" 2>stderr.log | grep '\.txt$' >>logfile
Explanation:
-m tells inotifywait to keep running. The default is to exit after the first event
-e delete tells inotifywait to only report on file delete events.
--format "%w%f" tells inotifywait to print only the name of the deleted file
path is the target directory to watch.
-r tells inotifywait to monitor subdirectories of path recursively.
2>stderr.log tells the shell to save stderr output to a file named stderr.log. As long as things are working properly, you may ignore this file.
>>logfile tells the shell to redirect all output to the file logfile. If you leave this part off, output will be directed to stdout and you can watch in real time as files are deleted.
grep '\.txt$' limits the output to files with .txt extensions.
Mac OSX
Similar programs are available for OSX. See "Is there a command like “watch” or “inotifywait” on the Mac?".
I have created a script which pick the files from a directory inbox. I have to include a handling in the script whether files are coming from another process or not. if files are coming through another process then my script should wait until files are copied.
For this i have create a flag
CHECK_COPY_PROCESS=$(ps -ef|grep -E 'cp|mv|scp'|grep inbox)
if flag CHECK_COPY_PROCESS contains some value then process will go to waiting state. but problem is that suppose some files are coming from sub directory of that directory inbox
then process will generate like this cp file_name .. above logic is not working.
You could use the tip of Basile, using lsof in conjunction with awk (grepping only on the first column, which is the command name)
Example:
lsof +D /path/to/inbox|awk '$1~/mv|cp|scp/'
This is not tested as I currently don't have big files that take a while to copy on my machine.