Last active
March 9, 2022 21:56
-
-
Save leucos/d3d8b2686ba8ab46c64a6f01d3ef9f53 to your computer and use it in GitHub Desktop.
This program moves files form one machine to another
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -eu | |
# | |
# This program watches new files and moves them from one machine to another | |
# | |
# How it works | |
# | |
# mover.sh will recursively watch changes in a directory using inotifywait. | |
# When the file is closed (after a write), the file is rsynced to the | |
# destination directory and removed from the local filesystem. | |
# | |
# If a directory is created, inotifywait will be restarted so it creates | |
# watches in the newly created directories. | |
# | |
# Since files can be created in a new depp directory hierarchy, we make use of | |
# rsync's -R flag and 'dotted' path (hence the requirement for rsync 2.6.7). | |
# | |
# For instance, if you run: | |
# | |
# mover.sh /tmp/a/ /tmp/b/ user@host | |
# | |
# and create a file 'foo' in /tmp/a/x/y/z/, hierarchy '/tmp/b/x/y/z/' might not | |
# exist on the remote system. | |
# | |
# This script takes care of this using the aformentioned options, and will | |
# execute: | |
# | |
# rsync -Ravz --remove-source-files /tmp/a/./x/y/z/foo [email protected]:/tmp/b/ | |
# | |
# which will take care of 'mkdir -p /tmp/b/x/y/z' before syncing foo. | |
# | |
usage() { | |
echo -e "Usage: $0 <SRC> <DST> [REMOTE]\n" | |
echo -e "\tSRC: absolute path of source to check" | |
echo -e "\tDST: absolute path of destination to copy to (on the remote if specified)" | |
echo -e "\tREMOTE: remote machine to copy to (in ssh form, e.g. [email protected])" | |
} | |
move() { | |
local src=$1 | |
local dst=$2 | |
local remote=$3 | |
# if we have a remote, prefix dst with it | |
if [ -n "$remote" ]; then | |
dst="$remote:$dst" | |
fi | |
# -R makes use of relative paths | |
echo rsync -Ravz --remove-source-files $src $dst | |
# Uncomment for real action | |
# rsync -Ravz --remove-source-files $src $dst | |
} | |
monitor() { | |
local src=$1 | |
local dst=$2 | |
local remote=$3 | |
while read res; do | |
op=$(echo "$res" | cut -f1 -d' ') | |
dir=$(echo "$res" | cut -f2 -d' ') | |
file=$(echo "$res" | cut -f3 -d' ') | |
pruned=${dir#${src}} | |
echo "$res (pruned: ${pruned})" | |
case $op in | |
*ISDIR) | |
echo "directory ${dir} created" | |
break | |
;; | |
CLOSE_WRITE*) | |
echo "$op TRIGGERS => move ${src}./${pruned}${file} ${dst} ${remote}" | |
move "${src}./${pruned}${file}" "${dst}" "${remote}" | |
;; | |
*) | |
echo "nothing to do for $op" | |
esac | |
done < <(inotifywait -r -m --format '%:e %w %f' -e create,close_write "$src") | |
} | |
source=$1 | |
destination=$2 | |
remote=${3:-} | |
if [ ! -r "$source" ]; then | |
echo "ERROR: source $source does not exist" | |
exit 1 | |
fi | |
if [[ "$source" != /* ]]; then | |
echo "ERROR: source $source path must be absolute" | |
exit 1 | |
fi | |
if [ ! -r "$destination" ]; then | |
echo "ERROR: destination $destination does not exist" | |
exit 1 | |
fi | |
if [[ "$destination" != /* ]]; then | |
echo "ERROR: destination $destination path must be absolute" | |
exit 1 | |
fi | |
if [ ! -r "$remote" ]; then | |
echo "WARNING: no remote specified; will work locally" | |
fi | |
while true; do | |
monitor "$source" "$destination" "$remote" | |
echo "Directory created, respawning" | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment