Script that uses variable username in find command

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?

Answers


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")

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.


Need Your Help

How do I make concurrently running threads?

java multithreading concurrency runnable

I want to have two separate threads running two different instances of different classes and I want them to execute the run command at the same time.

how do i get “this = this” in prototype working

javascript prototype this reverse

Ok peep's so I know it's bad practice to mess with prototypes but here it is anyway... Array.prototype.rev= function(){ this.reverse(); } Works fine! Updates the source array