11

I have this for loop for example that takes so much time to finish so I want to use tqdm to have a nice progress bar like in python. But I can't find any way to do it?

for f in `find mydir -name *.jpg -print`; do cp $f images/${f//\//_}; done

How can I get a progress bar for this loop?

yukashima huksay
  • 5,834
  • 7
  • 45
  • 78
  • better yet, search here for `[linux] find xargs parallel` . Assuming you have multiple cores and extra memory, you can process multiple files atht same time. Good luck. – shellter Jan 22 '18 at 04:35

3 Answers3

5

This is a really old question, but currently the readme for tqdm says that using it as a command in bash works fine, e.g.:

$ seq 9999999 | tqdm --bytes | wc -l
75.2MB [00:00, 217MB/s]
9999999

$ tar -zcf - docs/ | tqdm --bytes --total `du -sb docs/ | cut -f1` \
    > backup.tgz
 32%|██████████▍                      | 8.89G/27.9G [00:42<01:31, 223MB/s]

However, tqdm showing a progress bar is dependent on the command giving it information to build a progress bar from, which cp doesn't (even cp -v doesn't send buffered info, so you'll only get the progress bar once cp completes).

That said, if you want a progress bar for copying files you should like into either rsync --progress or the pv command.

Using rsync, the command to solve your question could be something like:

rsync -avzh --progress **/*.jpg images/
APaul
  • 376
  • 4
  • 15
5

To use tqdm in a Bash loop, you need:

  1. to output something
  2. to know the total number of iterations (optional)
  3. to add tqdm after the done.

In your case:

total=1000
for f in `find mydir -name *.jpg -print`; do echo $f; cp $f images/${f//\//_}; done | tqdm --total $total >> /dev/null

See the answer: https://github.com/tqdm/tqdm/issues/436#issuecomment-330504048

guhur
  • 2,500
  • 1
  • 23
  • 33
-7

tqdm is dedicated for python, not for bash.. Instead, if you just want to display the progress of your loop, you may just need a "symbolic" progress bar, like the answer by @Mitch Haile to the question How to add a progress bar to a shell script?

You may need to calculate the progress by (executed loops number)/(total loops number) according to your need. E.g.

Loop_array=(`find mydir -name *.jpg -print`);
Total_loop_num=${#Loop_array[*]};
for((i=0;i<$Total_loop_num;i++))
do
   echo -ne "Progress: $[ ($i+1)*100/$Total_loop_num ]%\r";
   f=${Loop_array[$i]};
   cp $f images/${f//\//_};
done;
echo "Loop finished.";

It should work as long as your original commands work. I've just tested on the following code and it works fine:

for((i=0;i<120000;i++))
do
   echo -ne "Progress: $[ ($i+1)*100/120000 ]%\r";
done;

If you also want a "real" progress bar like the series of "#", you can calculate for every N loops to add a "#" to a string then echo it.

LDecem
  • 7
  • 5
  • @yukashimahuksay Thanks. I actually don't know about tqdm and I don't have it installed either. I just google and found it a module of python. – LDecem Jan 26 '18 at 11:36
  • 3
    You, sir, didn't read the manual which gives a nice introduction on using tqdm in the terminal ;) – Jakob Guldberg Aaes Mar 27 '21 at 04:53