So I think I have a little user right issue. Have been scripting a Webserver Control panel.
At a point in this script I'm listing all folders for a user into an array so I can compare it to the user input. (Each user is a new customer, and each customer can have multiple sites). Up until Friday last week when I ran this command:
[rjo@WEB ~]$ sudo ls -d /home/hejhej/*/ 2>/dev/null
Everything was working fine running the command from my own user (rjo). But now when I run the command nothing happens, so I removed "2>/dev/null" and tried again and now I'm getting this:
[rjo@WEB ~]$ sudo ls -d /home/hejhej/*/
ls: cannot access /home/hejhej/*/: No such file or directory
But when running it from root everything works fine:
[root@WEB ~]# ls -d /home/hejhej/*/
/home/hejhej/bumbum.dk/
Here's the line regarding my user from visudo file.
rjo ALL=(ALL) NOPASSWD: ALL
If you need any other info to help pleas tell me and I will post.
This will happen if your user doesn't have enough permissions on /home/hejhej
to list its contents.
When you run:
sudo ls -d /home/hejhej/*/
It is your shell that tried to do filename globbing. If it can't read that directory, it can't expand anything. So the literal string /home/hejhej/*/
is left as is, and passed as an argument to the ls
run by root
via sudo
. It appears you don't have a directory called *
in that directory, so ls
fails.
You need the shell started by sudo
to do the globbing here. One option might be:
sudo sh -c 'ls -d /home/hejhej/*/'
If you want the folder to search to contain a shell variable, then the '
hard quotes won't do - this prevents your shell from globbing (good) but also prevents variable expansion by your shell (bad here). You should use double-quotes ("
) instead so that variable expansion is done by your shell:
sudo sh -c "ls -d /home/$username/*/"
If you want to capture the ouput of that command into a variable, prefer the $()
form of command substitution rather than backticks (`
) - easier for quoting:
result=$(sudo sh -c "ls -d /home/$username/*/")
Now if $username
can contain spaces (say username="hello world"
), what is above won't work - the root shell will see two "tokens" (/home/hello
and world/*/
). You can fix that with another layer of quotes:
result=$(sudo sh -c "ls -d /home/'$username'/*/")
Given how the quotes are nested, this will not prevent your shell from expanding $username
, but will enable the root shell to glob correctly on the single pattern /home/hello world/*/
.
Now, this is still not perfect. You'll have a hard time dealing with issues if that glob matches more than one directory, or if the directory matched contains spaces. But at this point I'd advise you to:
That being said, if you want a list of directories from another user's home into an array, the following (bash specific I think) should do it, without the problems of parsing ls
, and should handle spaces in files and directories:
while read -r -d $'\0' dir ; do
array+=("$dir")
done < <(sudo find "/home/$username" -maxdepth 1 -mindepth 1 -print0)