Linux / UNIX Bash: Copy Set of Files to All Users Home Directory

If you would like to copy a set of files for all existing users, use the following scripting trick. It will save lots of manual work.

First you need to grab all user names from /etc/passwd file using the cut command:
# cut -d: -f1 /etc/passwd
However, the above will grab all system account too. To grab only user account (UID >= 500), enter:
# awk -F':' '{ if ( $3 >= 500 ) print $1 }' /etc/passwd
Next, you can use the shell for loop command to copy file(s) and set the correct permissions on the file. The id command can be used to obtain the correct user ID and group ID for each user.

Copy Single File To All Users Home Directory

 # get list of all users
_USERS="$(awk -F':' '{ if ( $3 >= 500 ) print $1 }' /etc/passwd)"
for u in $_USERS
   if [ -d "$_dir" ]
       /bin/cp "$FILE" "$_dir"
      chown $(id -un $u):$(id -gn $u) "$_dir/${FILE}"

Copy Multiple Files To All Users Home Directory

You can also copy multiple files using inner and outer loop concept:

# note wild card allowed
_FILES="/etc/skel/.newconfig-file /etc/skek/.update-config /chroot/jail/.force.conf /nas05/perl/*.pl"
_USERS="$(awk -F':' '{ if ( $3 >= 500 ) print $1 }' /etc/passwd)" # get list of all users
for u in $_USERS
  for f in $_FILES
     if [ -d "$_dir" ]
       /bin/cp -f "${f}" "$_dir"
       chown $(id -un $u):$(id -gn $u) "${_dir}/${f}"

As pointed out by our readers (see comments below), you need to add additional security check such as:

  • User should be a normal user (hint: use awk -F’:’ { if ( $2 >= 500 )… )
  • User must have a directory (hint: use [ -f dir ] syntax)
  • User must have a valid password / account. (hint: use /etc/passwd to verify the same)

This is left as exercise for the reader.

Updated for accuracy.

🐧 Get the latest tutorials on Linux, Open Source & DevOps via RSS feed or Weekly email newsletter.

🐧 12 comments so far... add one

CategoryList of Unix and Linux commands
Disk space analyzersdf ncdu pydf
File Managementcat cp mkdir tree
FirewallAlpine Awall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network UtilitiesNetHogs dig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNAlpine CentOS 8 Debian 10 Firewall Ubuntu 20.04
12 comments… add one
  • Casper Pedersen Jan 3, 2008 @ 16:32

    This will also copy files to home directory of system users (not all of them have home directories).

    This will prevent that this happens.

    ID=$(id -u $u)
    if [ $ID -ge 1000 ] ; then
    if [ -d ${UHOME}/${u} ] ; then
    … do copy here….

  • 🐧 nixCraft Jan 3, 2008 @ 16:45


    Yeah, you got a valid point there.

    Appreciate your post.

  • Ilias Marinos Jan 3, 2008 @ 18:16

    marinosi@lucifer:~$ id -u nobody

    I’m pretty sure you don’t want to copy something to the nonexistent nobody’s homedir. 😛

    Someone , could have in the system other accounts that cannot login (or don’t have a home dir etc)..One way to find the active users of a system is :

    $ cat /etc/shadow | grep -v ‘[*!]’

    Users who are inactive(have disabled accounts ) have a * or $ (these users cannot login) at the field where they should have the password hash.

  • 🐧 nixCraft Jan 3, 2008 @ 18:38


    The post has been updated. Thanks for sharp observation.

  • Jeff Schroeder Jan 3, 2008 @ 21:19

    Instead of using cp… chown… use the install command. It does the same thing.

  • Vincent Jan 7, 2008 @ 1:25

    If you don’t have your users in /etc/passwd, but for instance in ldap, you can use `getent passwd` instead.

  • Alex Gretlein May 3, 2008 @ 22:32

    You also need to safely handle pre-existing files of the same name. You can use the –backup option with install or cp, but you probably want to log it and/or inform users in some way.

  • Indie Sep 11, 2009 @ 20:09

    The users home directory isn’t necessarily in the /home directory, you should read it from the ‘directory’ field in /etc/passwd – field 6
    UHOME=$(grep '^${u}' /etc/passwd | cut -d: -f6)

  • gerar Apr 8, 2011 @ 19:53

    hmm… errr…..

    if you chown $_dir/${FILE} then you are trying to chown a nonexistant file,
    as this expands to /home/user//nas05/.newconfig-file

    chown $(id -un $u):$(id -gn $u) “$_dir/${FILE}”

    Maybe if you created a new variable:

    then you changed the chown line:
    chown $(id -un $u):$(id -gn $u) “$_dir/${FILENAME}”
    it would expand properly?

  • xris Mar 30, 2012 @ 16:09

    What if I want to copy into a folder? (ie: ~Desktop/) or other and that folder does not exist.
    I know you can include a test to see if it exists or not, and create it if necessary.

  • 6lings Jun 18, 2013 @ 9:51

    Thanks for this post, was helpful
    For more compatibility with others OS than Linux (Solaris, HP-UX…) i get the uid / gid using old fashionned way
    _uid=”$(getent passwd | grep ${u} | cut -d: -f3)”
    _gid=”$(getent passwd | grep ${u} | cut -d: -f4)”

    and i get the users with getent aswell as i am using an LDAP
    _USERS=”$(getent passwd | awk -F’:’ ‘{ if ( $3 >= 500 ) print $1 }’)”

  • SiriZen Feb 13, 2015 @ 13:22

    Some modified version for multiple files copy, it’s not perfect code but it fork

    # note wild card allowed
    _FILES="/tmp/.bashrc /tmp/.bashrc-user"
    _USERS="$(awk -F':' '{ if ( $3 >= 500 && $3 <=1000 ) print $1 }' /etc/passwd)" # get list of all users
    for u in $_USERS
      for f in $_FILES
         if [ -d "$_dir" ]
           /bin/cp -f "${f}" "$_dir"
    	file_name=`basename ${f}`
           chown $(id -un $u):$(id -gn $u) "${_dir}/${file_name}"

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre> for code samples. Still have questions? Post it on our forum