Reading rsync source from file results in improper parsing of file names with white space

162 Views Asked by At

I wrote a simple script that searches through a specific directory defined by the variable "SCOPE" producing a list of directories that were modified within the past 24 hours printing them to a temp file. The first line of the file is deleted (to exclude the root level of the directory). Finally, it loops over the contents of the temp file and rsync's each of the directories to the destination.

Problem Directories that contain white space in their name do not rsync. The space causes everything before the whitespace and after the whitespace to be passed as individual arguments, and thus invalid filenames.

ObservationWhen I examine the contents of the temp file, each directory appears on a single line as expected. It appears that only when it is read into rsync from the file

How can I prevent the whitespace in the directory names from preventing those directories from failing to rsync?

SCOPE="/base/directory"           
DESTINATION="/volumes/destination/"       

find "$SCOPE" -maxdepth 1 -type d -mtime 0 > /tmp/jobs.txt;

sed '1d' /tmp/jobs.txt > /tmp/tmpjobs.txt;                      
mv /tmp/tmpjobs.txt /tmp/jobs.txt;

for JOB in `cat /tmp/jobs.txt`; do
    rsync -avvuh "$JOB" "$DESTINATION";          
done
3

There are 3 best solutions below

1
On BEST ANSWER

Replace

for JOB in `cat /tmp/jobs.txt`; do
    rsync -avvuh "$JOB" "$DESTINATION";          
done

by

while read -r JOB; do
    rsync -avvuh "$JOB" "$DESTINATION"
done < /tmp/jobs.txt
0
On

You want the -0 option for the rsync end, and the -print0 option for find. There's a lot of utilities that have some variation of this, so it's an easy fix!

From the find(1) manpage on Linux:

   -print0
          True; print the full file name on the standard output, followed by a null  character  (instead
          of  the  newline character that -print uses).  This allows file names that contain newlines or
          other types of white space to be correctly interpreted by programs that process the find  out-
          put.  This option corresponds to the -0 option of xargs.
1
On

If you don't need tmp file you can also use "one line" command:

find "$SCOPE" -maxdepth 1 -mindepth 1 -type d -mtime 0 -exec rsync -avvuh {} "$DESTINATION" \;

-mindepth 1 # This handle sed
-exec       # This handle whole loop