Q:

Jenkins Pipeline - better to perform workspace actions (copy files, create dirs, write symlinks, etc) in groovy or via sh steps?

I'm rewriting what is essentially a custom CI server into Jenkins pipeline jobs that heavily rely on a global pipeline library. 
So far, Jenkins pipeline has been an awesome tool, but I'm confused on a what the preferred method for writing steps is... are you better off writing the content of the steps in groovy, or shelling out with sh steps? The one major downside i see to using the sh step and shelling out a ton is that it's more difficult to handle errors. For example, if copying a dir of files errors out because the source dir doesn't exist, I want to handle that differently than if the target location is out of disk space. 
What is the preferred approach?

A:

Use sh steps. Anything you write in groovy will only run on the master server, while sh steps will run on the master and slave nodes. Pipeline is really only for flow control, with some steps built in to perform actions in workspaces.

