67

From the command line, I can get the home directory like this:

~/

How can I get the home directory inside my PHP CLI script?

#!/usr/bin/php
<?php
echo realpath(~/);
?>
Andrew
  • 227,796
  • 193
  • 515
  • 708

13 Answers13

85

Use $_SERVER['HOME']


Edit:

To make it complete, see what print_r($_SERVER)gave me, executed from the command line:

Array
(
    [TERM_PROGRAM] => Apple_Terminal
    [TERM] => xterm-color
    [SHELL] => /bin/bash
    [TMPDIR] => /var/folders/Lb/LbowO2ALEX4JTK2MXxLGd++++TI/-Tmp-/
    [TERM_PROGRAM_VERSION] => 272
    [USER] => felix
    [COMMAND_MODE] => unix2003
    [__CF_USER_TEXT_ENCODING] => 0x1F5:0:0
    [PATH] =>/Library/Frameworks/Python.framework/Versions/Current/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
    [PWD] => /Users/felix/Desktop
    [LANG] => de_DE.UTF-8
    [SHLVL] => 1
    [HOME] => /Users/felix
    [LOGNAME] => felix
    [DISPLAY] => /tmp/launch-XIM6c8/:0
    [_] => ./test_php2
    [OLDPWD] => /Users/felix
    [PHP_SELF] => ./test_php2
    [SCRIPT_NAME] => ./test_php2
    [SCRIPT_FILENAME] => ./test_php2
    [PATH_TRANSLATED] => ./test_php2
    [DOCUMENT_ROOT] => 
    [REQUEST_TIME] => 1260658268
    [argv] => Array
      (
        [0] => ./test_php2
      )

    [argc] => 1
    )

I hope I don't expose relevant security information ;)

Windows Compatibility

Note that $_SERVER['HOME'] is not available on Windows. Instead, the variable is split into $_SERVER['HOMEDRIVE'] and $_SERVER['HOMEPATH'].

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 9
    +1 it's amazing how many people gave the same plainly wrong answer to this simple question. – o0'. Jul 07 '10 at 09:52
  • I haven't any of the variables you post on Windows compatibility. I dump all SERVER array and there's no way to get my current profile, maybe due to admin rights used when launch wamp server. Any suggestion? – m3nda Feb 23 '14 at 03:39
  • @erm3nda: I'm sorry, I don't use Windows. The information about Windows compatibility was added by mauris. – Felix Kling Feb 23 '14 at 03:53
  • Finally i used a batch file to run the php script, using %PROFILE% as location and passing argv[1] to php. So now i can drag a php file to the batch and run it using my desktop as output directoriy. Is not cool, but it's the unique workaround i've found. Thank you. – m3nda Feb 25 '14 at 00:38
  • I don't have a `$_SERVER["HOME"]`. I am on Mac OS X 10.10 – Michael Feb 07 '15 at 21:20
  • @Michael: Strange, I do. – Felix Kling Feb 07 '15 at 22:27
  • Haven't tested it on windows neither on Mac, this might work though: $shell_user = posix_getpwuid(posix_getuid()); print_r($shell_user); – Francisco Luz Jun 18 '15 at 23:00
  • 2
    Try `getenv("HOME")` if `$_SERVER` and `$_ENV` don't work. – Andrea Nov 02 '16 at 20:27
  • I have `$_SERVER['HOME']` on Windows 10 and PHP.... 5.2 :P – Marco Sulla Jan 19 '23 at 14:58
65

You can fetch the value of $HOME from the environment:

<?php
    $home = getenv("HOME");
?>
EJ Campbell
  • 685
  • 5
  • 4
11

PHP allows you to get the home dir of any of the OS users. There are 2 ways.

Method #1:

First of all you gotta figure out the OS User ID and store it somewhere ( database or a config file for instance).

// Obviously this gotta be ran by the user which the home dir 
// folder is needed.
$uid = posix_getuid();

This code bit can be ran by any OS user, even the usual webserver www-data user, as long as you pass the correct target user ID previously collected.

$shell_user = posix_getpwuid($uid);
print_r($shell_user);  // will show an array and key 'dir' is the home dir

// not owner of running script process but script file owner
$home_dir = posix_getpwuid(getmyuid())['dir'];
var_dump($home_dir);

Documentation

Method #2:

Same logic from posix_getpwuid(). Here you gotta pass the target OS username instead of their uid.

$shell_user = posix_getpwnam('johndoe');
print_r($shell_user); // will show an array and key 'dir' is the home dir

// not owner of running script process but script file owner
$home_dir = posix_getpwnam(get_current_user())['dir'];
var_dump($home_dir); 

Documentation

Jürgen
  • 3
  • 1
Francisco Luz
  • 2,775
  • 2
  • 25
  • 35
  • It worked for me. I would just add to your answer `$shell_user['dir']` as the home directory is the question subject. – Hicaro Mar 15 '17 at 22:27
  • 1
    $tmp = posix_getpwuid(getmyuid()); ; // Linux safe $home = $tmp['dir']."/" ; –  Aug 24 '18 at 18:40
  • The reason I have not specifically mentioned $shell_user['dir'] is because I am not sure if the array variable naming applies to all OSs. – Francisco Luz Nov 28 '18 at 06:30
  • "posix_getpwnam(get_current_user())['dir'] still returns the homedir of the current user on Centos 7.7. Just to let you know if people are searching for this and are running a Centos 7 based webserver – NME New Media Entertainment Apr 23 '20 at 20:32
  • @NMENewMediaEntertainment That information is in the code sample comments. – Francisco Luz Apr 27 '20 at 00:39
  • 1
    In posix, you can set the effective UID (for example, working as root on behalf of a user), so you may want to use posix_geteuid instead of posix_getuid, if the request may relate to the effective user. They return the same thing if an effective user has not been set, so no harm if that is the case. – wordragon Dec 16 '20 at 23:23
9

This function is taken from the Drush project.

/**
 * Return the user's home directory.
 */
function drush_server_home() {
  // Cannot use $_SERVER superglobal since that's empty during UnitUnishTestCase
  // getenv('HOME') isn't set on Windows and generates a Notice.
  $home = getenv('HOME');
  if (!empty($home)) {
    // home should never end with a trailing slash.
    $home = rtrim($home, '/');
  }
  elseif (!empty($_SERVER['HOMEDRIVE']) && !empty($_SERVER['HOMEPATH'])) {
    // home on windows
    $home = $_SERVER['HOMEDRIVE'] . $_SERVER['HOMEPATH'];
    // If HOMEPATH is a root directory the path can end with a slash. Make sure
    // that doesn't happen.
    $home = rtrim($home, '\\/');
  }
  return empty($home) ? NULL : $home;
}
ya.teck
  • 2,060
  • 28
  • 34
5

If for any reason getenv('HOME') isn't working, or the server OS is Windows, you can use exec("echo ~") or exec("echo %userprofile%") to get the user directory. Of course the exec function has to be available (some hosting companies disable that kind of functions for security reasons, but that is more unlikely to happen).

Here is a function that will try $_SERVER, getenv and finally check if the exec function exists and use the appropriate system command to get the user directory:

function homeDir()
{
    if(isset($_SERVER['HOME'])) {
        $result = $_SERVER['HOME'];
    } else {
        $result = getenv("HOME");
    }

    if(empty($result) && function_exists('exec')) {
        if(strncasecmp(PHP_OS, 'WIN', 3) === 0) {
            $result = exec("echo %userprofile%");
        } else {
            $result = exec("echo ~");
        }
    }

    return $result;
}
Christos Lytras
  • 36,310
  • 4
  • 80
  • 113
  • The block with the shell-commands is nice, the rest is "second-hand" and might not be reliable. – David Mar 03 '19 at 01:29
  • @David this is just a function to get the home dir; Don't know what do you mean by "second-hand"; that I know is I'm using this function to retreive home dir in windows and linux for a long time without any failures. What's unreliable? the fact that there won't be a home dir result if `$_SERVER['HOME']` or `getenv("HOME")` return an empty? or `PHP_OS` starts with `WIN` on windows systems? – Christos Lytras Mar 04 '19 at 06:42
  • You got the point already, servers today are recommended to expose as little as possible and often it's either not configured or suppressed that "HOME" is leaking information. Furthermore the info is - if available - read by the server-software and then provided in that kind indirectly as it's not read directly by the system - so theoretically the value could be even wrong too. I tested it on Linux, so it's not an OS-issue. Nevertheless, I like the second half of your snippet and used it to create a merged version of your solution and that of @Francisco Luz without any global variables. – David Mar 04 '19 at 07:56
  • " so theoretically the value could be even wrong too" I meant it could be *intentionally* – David Mar 04 '19 at 08:07
  • You don't get the point that this type of methods are used for CLI scripting and if a server populates "fake" or empty values for the **shell access allowed** users, then the server itself is unreliable. If you use methods like this to store files uploaded by a user, then all kind of such methods will be unbreliable. I'm still waiting you to point out the "unreliable" part of this method other than "servers today (do)/(should) not provide such sensitive information". There is a huge difference between users that can execute CGI scripts and users with shell access that can execute CLI scripts – Christos Lytras Mar 04 '19 at 08:17
  • Many security measures that are taken by different parties. Some disable "exec", some disable all the "posix" functions and others disable some global variables. I know this is used for scripting and often a pain in the ass if you can't access some commands or info. Nevertheless global variables are the best way to expose information by accident, while not restricted access to CLI has other risks. Discussing about those things can be hard with every company that is making you somehow a hard time by individual and often illogical arguments, might be due to experience with common web-developers. – David Mar 04 '19 at 08:38
  • 1
    The fact is this method is just a piece of code that most users will/must use for creating their own custom scripts. The systems that the scripts will run and the enviroment these systems will support is a totally different story, thus you can't say a piece of code is unreliable *in general*; maybe it's unreliable under some **circumstances** and **cases**, but it's not unreliable for the main purpose it's written for and that is **persmission gnostic systems** and not shared 3rd party hosting provider servers. Hostings with shell access should have different security settings for the CLI. – Christos Lytras Mar 04 '19 at 10:07
2

This works for me both LINUX and WINDOWS:

function get_home_path() {
  $p1 = $_SERVER['HOME'] ?? null;       // linux path
  $p2 = $_SERVER['HOMEDRIVE'] ?? null;  // win disk
  $p3 = $_SERVER['HOMEPATH'] ?? null;   // win path
  return $p1.$p2.$p3;
}
Vladimir Buskin
  • 614
  • 4
  • 8
  • 2
    Good to know about the vars, but why do you concatenate all the paths together? What if both `HOME` and `HOMEPATH` happened to be set? – Christian Aug 17 '22 at 09:53
  • because, I've checked in Windows and Linux, It was not possible HOME and HOMEPATH be there at the same time, one of them is Empty. You might be right if they change it in the future versions. – Vladimir Buskin Nov 22 '22 at 00:56
  • Note that it's not recommended to concatenate NULL values, at least concatenate empty strings. But, a better logic should really be: if + return the first available – Valerio Bozz Apr 29 '23 at 20:47
2

Depends on where you are and what you're trying to do.

$_SERVER is completely unreliable for a non-server script, BUT $_ENV['HOME'] might be better for a standard shell script. You can always print_r( $GLOBALS ) and see what your environment gives you to play with. phpinfo() also spits out plaintxt when called from a CLI script, and just good ole php -i executed from a shell will do the same.

-1

This is the method i used in a recent project:

exec('echo $HOME')

I saved it into my object by doing this:

$this->write_Path  = exec('echo $HOME');

But you could really save it any way you want and use it anyway you see fit.

dustbuster
  • 79,958
  • 7
  • 21
  • 41
-1

You can rely on "home" directory when working with web server. Working CLI it will give the user path (in windows) if you want your script to work in web and cli environments I've found better to go up any levels with dirname until your root(home) directory.

echo dirname(__DIR__).PHP_EOL; // one level up
echo dirname(dirname(__DIR__)); //two levels up
echo dirname(__DIR__,2).PHP_EOL; //two levels only php >7.0
lisandro
  • 454
  • 4
  • 12
-2

I know that this is an old question, but if you are looking for an alternative and easy to replicate method across your application, you may consider using a library installed via composer. I've written a library that combine some of the answer here and make it a library and I'll shamelessly promote it here : juliardi/homedir.

You can install it via composer :

$ composer require juliardi/homedir

And then use it in your application :

<?php

require_once('vendor/autoload.php');

$userHomeDir = get_home_directory();

Hope this answer help you.

ardi
  • 5
  • 2
-7

$_SERVER['HOME'] and getenv('home') did not work for me.

However, on PHP 5.5+, this worked to give the home directory that the file is located in:

explode( '/', __FILE__ )[2]
iateadonut
  • 1,951
  • 21
  • 32
  • 3
    The issue with this approach is that user home folders are not always located at /home/username. On shared hosting it could be something like /home/storage/xxx/xxx/xxx/username – Francisco Luz Jun 18 '15 at 22:55
-11

Try $_SERVER['DOCUMENT_ROOT'] as your home directory.

phant0m
  • 16,595
  • 5
  • 50
  • 82
  • Welcome to StackOverflow. Please take a look at the [**formatting explanation**](http://stackoverflow.com/editing-help) when you have some time. Thank you. – phant0m Nov 29 '12 at 19:04
  • 2
    This is plain wrong. In almost all sites, DocumentRoot !== $HOME. However, the OP is talking about CLI, where $_SERVER['DOCUMENT_ROOT'] isn't even set, as it has no relevance. – spikyjt Jan 21 '13 at 15:27
-18
dirname(__DIR__);
streetparade
  • 32,000
  • 37
  • 101
  • 123