There are already some really great answers here, but here are my favorite commands, including my own little spin on the rsync command, with my favorite options:

1. watch 'du -hs' (or, for more granularity: watch -n 1 'du -sk | awk '\''{printf "%.3f MiB %s\n", $1/1024, $2}'\''') allows you to watch a destination folder grow in size if cp is already running

What if you already started a long cp process and don't want to stop it now?

Assuming you already started this copy command:

# recursively copy source_dir_name to destination
cp -r source_dir_name destination

Just open up a new terminal, with the copy operation already in progress, and run:

# cd into destination directory
cd path/to/destination/source_dir_name

# Now watch, live, the size of this destination grow!
watch 'du -hs'

# OR (Preferred!) see even more granularity, in X.xxx MiB: 
watch 'du -sk | awk '\''{printf "%.3f MiB %s\n", $1/1024, $2}'\''' 

This will cause the watch command to automatically run du -hs (or du -sk | awk '{printf "%.3f MiB %s\n", $1/1024, $2}') every 2 seconds (the default for watch) inside your destination directory, so you can see the size of the folder grow in real-time! This doesn't give you a percentage complete, but if you have a rough idea of the size of what you're copying, it certainly gives you something to watch and feel good about, knowing the destination is growing. Here's a sample output on the watch screen:

  1. Cmd: watch 'du -hs'

    Output:

    Every 2.0s: du -hs
    
    2.5G    .
    
  2. Cmd: watch 'du -sk | awk '\''{printf "%.3f MiB %s\n", $1/1024, $2}'\'''

    Output:

    Every 2.0s: du -sk | awk '{printf "%.3f MiB %s\n", $1/1024, $2}'
    
    2560.348 MiB .
    

Above, you can see the current size of the current directory (.) is 2.5 GiB, or, more specifically in the 2nd case: 2560.348 MiB. To make watch use a slower update interval, such as 5 seconds, just add -n 5 to the watch command, like this:

watch -n 5 'du -hs'

# OR (preferred, for more granularity)
watch -n 5 'du -sk | awk '\''{printf "%.3f MiB %s\n", $1/1024, $2}'\'''

2. rsync really is best for this

My favorite commands:

# dry-run
time rsync -rah --dry-run --info=progress2 --stats source destination

# real copy (Important! Do a dry run first and read the
# output summary to ensure you're copying what you intend!)
time rsync -rah --info=progress2 --stats source destination

Note: the time part at the front of the above commands just outputs a nice time summary of the total run-time for the operation in the end. This works before any Linux command.

Here's what an rsync --stats summary for a --dry-run looks like, by the way:

$ rsync -rah --dry-run --info=progress2 --stats /media/gabriel/cdrom ~/temp
          2.76G 100% 2570.10GB/s    0:00:00 (xfr#3836, to-chk=0/4837)   

Number of files: 4,837 (reg: 3,836, dir: 1,001)
Number of created files: 0
Number of deleted files: 0
Number of regular files transferred: 3,836
Total file size: 2.76G bytes
Total transferred file size: 2.76G bytes
Literal data: 0 bytes
Matched data: 0 bytes
File list size: 0
File list generation time: 0.001 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 123.88K
Total bytes received: 15.54K

sent 123.88K bytes  received 15.54K bytes  278.85K bytes/sec
total size is 2.76G  speedup is 19,792.78 (DRY RUN)

References

  1. Place where I first documented the watch -n 5 'du -sk | awk '\''{printf "%.3f MiB %s\n", $1/1024, $2}'\''' type command, in my ROS tutorial: my ROS.org tutorial: Reading messages from a bag file

Extra reading

  1. My long answer on some advanced rsync usage and stuff: Super User: Convert NTFS partition to ext4 - How to copy the data?
  2. [another one of my answers] Unix & Linux: Is it possible to see cp speed and percent copied?