1

I'm performing an rsync process to copy files from an SD card and I want to show the progress per file in Zenity during the rsync process per file. I tried Zenity and rsync which seemed perfect for me. It should send the current file and % copied to Zenity, but I cannot get it to, output is not realtime and does not move the progress bar. And I could not figure out why its not working.

What I'm trying to do at the least is send the percentage of the file copy into Zenity to drive the progress bar. But this needs to be a number without the trailing % to drive the progress bar.

This does not output anything, but if I remove the sed and Zenity steps then I get: 0%, 1%, 2% etc. But Zenity requires non percentage values.

sudo rsync -av  --info=progress2  "$f"/*.MP4 $copydest | \
strace -e trace=read grep "[0-9]*%" 2>&1 > /dev/null | grep -o "[[:digit:]]*%" | sed 's/[^0-9]//g' | \
zenity  --width=400 --height=20 --progress  --percentage=0  --text="Copying...." --auto-close  --auto-kill \
 --title="Copying $tc from  $cardname"

Ideally, I would like the current filename to display as well, but I'm stuck. For example,

Filename.MP4
.......... (progress)

There must be a recipe in grep or sed or awk that I can grab the MP4 file name and the % of copied as a number, but its beyond me.

Here's what rsync will output on 3 files with incrementing % and time remaining etc

25_nn67_P1680210.MP4
  1,024,202,031 100%  163.00MB/s    0:00:05 (xfr#1, to-chk=2/3)
25_nn67_P1680211.MP4
    146,801,421 100%   49.12MB/s    0:00:02 (xfr#2, to-chk=1/3)
25_nn67_P1680212.MP4
jww
  • 97,681
  • 90
  • 411
  • 885
Nowski
  • 173
  • 1
  • 14

3 Answers3

4

Okay, I fixed it, thanks so much to dash-o for the formatting help - worked a treat. Problem was pipe buffering, so Zenity was not getting any data until the buffer was full - which may have been never with the set of test files I was running. You need to set the buffer for all steps in the pipe (prior to zenity) to 0:

sudo  rsync -av  --info=progress2  "$f"/*.MP4 $copydest | \
stdbuf -i0 -o0 -e0 tr '\r' '\n' | stdbuf -i0 -o0 -e0  awk -W interactive -f /path/to/rsync.awk |  zenity --progress  --width=400   --text="Copying...." --auto-close --title="Copying $cardname"  

Then in rsync.awk (it may work without the need for the extra file) adding fflush() ensures it refreshes.

#!/bin/sh
/^ / { print int(+$2) ; fflush() ;  next } $0 { print "# " $0  }

So now, executing the rsync (via a previous Zenity dialogue) results in the progress window, with the current filename and a moving progress bar while Rsync copies each file - note: not overall progress, but for each file copied as it happens.

So now my script is triggered on insertion of an SD card containing MP4 files, and copied using rsync, with working progress bar.

Nowski
  • 173
  • 1
  • 14
  • nice trick. however instead of an additional rsync.awk file, one could just type `... awk -W interactive '/^ /{ print int(+$2); fflush(); next}$0{ print "# " $0}' | zenity ...` – cipper Jan 02 '23 at 14:06
2

One relative simple option is to capture the current file, and % of current file:

rsync -av --info=progress2 ...  |
   tr '\r' '\n' |
   awk '/^ / { print int(+$2) ; next } $0 { print "# " $0 }' |
   zenity --progress ...
dash-o
  • 13,723
  • 1
  • 10
  • 37
  • Thanks so much for the help, I see #filename followed by numbers (without %) - when I test via CLI Excellent! but for some reason Zenity will not read that – Nowski Nov 25 '19 at 14:56
  • this is how I zenity is called: ``` zenity --width=400 --height=20 --progress --percentage=0 --text="Copying...." --auto-close --auto-kill --title="Copying $cardname" – Nowski Nov 25 '19 at 15:03
  • what is the meaning of `$0` placed between the `} {` ? – cipper Jan 02 '23 at 14:12
  • 1
    @cipper - The '$0' check if the current line is not empty. – dash-o Jan 02 '23 at 17:25
  • @dash-o so it's equivalent to `NF>0`? still it's not clear to me what is the check. `$0>a` seems true for any value `a` – cipper Jan 03 '23 at 18:28
  • @cipper, $0 is not >"", if $0 = "" – dash-o Jan 04 '23 at 10:25
  • @dash-o that I understand. But if I write `echo aaaa | awk '$0>5{print}'` it prints `aaaa`, while if I write `echo aaaa | awk '$0<5{print}'` the output is null. Why? How does `$0` compare with a number? If i replace 5 with any number the output is the same. – cipper Jan 05 '23 at 11:08
0

It is more challenging to show overall completion rate. This will require running rsync twice - once in dry-run mode, to count the number of files to be moved, and then to use the file count to calculate percentage progress.

Needless to say, this will add slightly delay to the actual copy.

The code below assumes all files take same amount of time to copy. It need some work to perform actual estimation of file count, as the log contain few other messages (total bytes, etc).

(
echo "5" ; echo "Calculate job Size"
file_count=$(rsync --dry-run -av  feature_files/ fff/ | wc -l)
echo "F=$file_count"

rsync -av --info=progress2 feature_files/ fff/ |
   tr '\r' '\n' |
   awk -v "total=$file_count" '
/^ / { print 100*(count+$2/100)/total ; next }
$0 { print "# " $0 ; count++ ; print 100*count/total }
'
) | zenity --progress ...
dash-o
  • 13,723
  • 1
  • 10
  • 37
  • Actually I'm not after the total rsync process, but per file as it goes, so that the dialog will stay open while transfers are happening and show the progress of each one - does that make sense – Nowski Nov 25 '19 at 17:05
  • @Nowski I've posted two options, as I was not sure which version you want. Take the one that fit you requirement! – dash-o Nov 25 '19 at 18:04
  • Yes thanks, the first one seems to be the one which outputs the correct format data - much appreciated, but for some reason Zenity will not accept it, I'll persevere - thank you again, – Nowski Nov 26 '19 at 08:33