0

I'm trying to write a script that lists the absolute paths of all of a given user's home files and directories, recursively, and writes all of them to an array. Currently, I'm using find like so ...

user="foobar"
usersHomeFiles=( $(find ~$user -printf "%p\\n") )

However, when I execute this script it tells me ...

find: `~foobar': No such file or directory

Even though foobar is a valid user with a home directory. I even get the same error running it with user="root". Any ideas how I could fix this so the find command works in my script?

user2150250
  • 4,797
  • 11
  • 36
  • 44

3 Answers3

2

Tilde expansion occurs prior to parameter expansion, so the tilde ~$user is left as-is. You'll need something like

userHome=$( eval "echo ~$user" )
userHomeFiles=( $( find "$userHome" -print '%p\n' ) )

although I hope someone will post an eval-free solution. This is not safe unless you are absolutely sure of the contents of user.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • to avoid eval, couldn't you do something like userhome=$( echo "~${user}" )... nope, just tried it and that doesn't work. – senorsmile May 02 '13 at 18:35
2

This happens because in bash "tilde expansion" happens before "parameter expansion". So tilde expansion attempts to find user "$user", this fails and the tilde remains unchanged. Next comes "parameter expansion" substituting "$user" with "foobar". See bash(1) "EXPANSION" section.

One way to do this is with "eval", like this:

user_home=`eval "echo ~$user"`

Another is directly querying the passwd database, like this:

user_home=`getent passwd "$user" | cut -d: -f6`

However, note that your array assignment will break if user home directory contains filenames with spaces or tabs.

You can read them more reliably with "readarray", like this:

readarray -t usersHomeFiles < <(find "$user_home")
spbnick
  • 5,025
  • 1
  • 17
  • 22
0

You may need to add a couple of options to your find command, i.e. the path where find starts to search from and the -name flag i.e.:

$(find /home/$user -name "*" -printf "%p\\n")