4

So I have the following path: /my_user/path/to/dir, and when I pass it to file_exists(), it works fine.

However, when I change it to ~username/path/to/dir, it returns false.

realpath("~username/path/to/dir") returns false as well.

What can be wrong?

Note: This is not a duplicate of How to get the home directory from a PHP CLI script? because I'm more curious about why the tilde doesn't work, rather than how to work around it.

miken32
  • 42,008
  • 16
  • 111
  • 154
tera_789
  • 489
  • 4
  • 20
  • Do you need to add a `/` after the `~`? e.g. `~/username/path/to/dir` – Ethan Nov 27 '18 at 00:00
  • No. `ls ~/username/path/to/dir` work fine as well as `cd` – tera_789 Nov 27 '18 at 00:00
  • 1
    I mean in your PHP, not in the terminal. – Ethan Nov 27 '18 at 00:01
  • The tilde symbol (~) in OS X command-line terminology refers to your home directory, e.g /Users/Joe. Can you not use this instead? It may not know what ~ means. – MomasVII Nov 27 '18 at 00:02
  • @Davіd No, still does not work... – tera_789 Nov 27 '18 at 00:02
  • @ThomasByy Yes I know, but the problem is that home directory of a user can change. So I do not want to hard code it. – tera_789 Nov 27 '18 at 00:03
  • @ThomasByy I do not need a home directory... I need a home directory of a specific user, which is very different thing from home directory of a server – tera_789 Nov 27 '18 at 00:05
  • `~` is expanded by shell, that's why `realpath` wouldn't work – zerkms Nov 27 '18 at 00:06
  • The system's environment variables are available in $_ENV or (in case they are not for you) can be made available there by adjusting the server config, – Johannes H. Nov 27 '18 at 00:06
  • Possibly a duplicate: https://stackoverflow.com/q/20535474/251311 – zerkms Nov 27 '18 at 00:07
  • Aaaaaaactually, nevermind. The OP is trying to use ANOTHER USER's home directory - neither the server user, nor the script user, but a random one. This information is not available to PHP (and should not be), but can be obtained reading and parsing `/etc/passwd`. – Johannes H. Nov 27 '18 at 00:08
  • @JohannesH. "is not available to PHP" --- http://php.net/manual/en/function.posix-getpwuid.php – zerkms Nov 27 '18 at 00:09
  • @zerkms this function does basically what I said: read nad parse /etc/passwd. What I meant by "not available" was refering to my first comment, where I mentioned $_ENV. – Johannes H. Nov 27 '18 at 00:09
  • @zerkms great idea. I even forgot about POSIX functions. I will try right now. If you want, write it as an answer and I will accept it – tera_789 Nov 27 '18 at 00:10
  • I bet you didn't read all the answers to the question you think this is not a duplicate of. Because your question is answered by Francisco Luz 3 1/2 years ago there. https://stackoverflow.com/a/30926828/1255289 – miken32 Nov 27 '18 at 02:16
  • @miken32 everyone who says my question is duplicate misunderstands my question. I am not asking how to get user's home directory! I am asking why `file_exists()` is not interpreting tilde! Can you see the difference? – tera_789 Nov 27 '18 at 04:48
  • Because it’s not part of the filesystem. The expansion into a directory name is a shell feature. You say in your question "I need a home directory" so I guess that's what people will think you are asking. – miken32 Nov 27 '18 at 04:50

2 Answers2

6

Tilde expansion is a shell feature, so its use outside the context of a shell (or another program in which the developer has chosen to implement this shell feature) is not possible, as it is not intrinsic to the filesystem or any other part of the OS.

The behaviour is defined in section 2.6.1 of the POSIX specification. The introduction to that chapter states:

The shell is a command language interpreter. This chapter describes the syntax of that command language as it is used by the sh utility and the system() and popen() functions defined in the System Interfaces volume of POSIX.1-2017.


If you want to use such a filename, you can use some of PHP's built-in functions to expand it:

<?php
$dir = "~username/bar/baz/";
$dirparts = explode("/", $dir);
array_walk(
    $dirparts,
    function(&$v, $k) {
        if ($v[0] ?? "" === "~") $v = posix_getpwnam(substr($v, 1))["dir"] ?? $v;
    }
);
$expanded = implode("/", $dirparts);
echo $expanded;
miken32
  • 42,008
  • 16
  • 111
  • 154
  • Great solution / workaround. However, to keep code clean and readable, I just decided to simply go with `posix_getpwnam(username)['dir']` and abandon use of tilde at all here. – tera_789 Nov 28 '18 at 08:16
3
$home_dir = exec( 'echo ~' ) ;
kitchin
  • 774
  • 6
  • 9