На замену realpath, который работает только с реально существующими файлами и папками UNIX, а также не работающий для ссылок, я написал функцию получения канонического пути.
В документации встречается функция eio_realpath, которая требует подключения libeio пакета. Описание её очень лаконичное, и возможно, она точно также работает лишь с реальными файлами, не позволяя получить канонизированный путь (realpath) для несуществующего в системе файла.
Get_canonical_path функция
Функция get_canonical_path($path) зачищает путь от возможных элементов вроде // или /./ и вычисляет навигацию /../. Также канонический путь не содержит в конце слеш.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
/** * Returns canonicalized pathname of a directory * @param string absolute path to be reduced * @return string absolute reduced path or NULL if the path could not get canonicalized. */ function get_canonical_path( $path ) { // Remove windows backslashes: $path = str_replace( '\\', '/', $path ); // Make sure there's a trailing slash $path = trailing_slash($path); $path = str_replace( '//', '/', $path ); $path = str_replace( '/./', '/', $path ); while( ($realpath = preg_replace( '#(^|/)([^/^.]+)/\.\./#', '$1', $path )) != $path ) { // While we find /../ back references to dereference... $path = $realpath; } if ( strpos( $realpath, '..' ) !== false ) { // Path malformed: return NULL; } return no_trailing_slash($realpath); } /** * Remove trailing slash, if present * * @param string the path/url * @return string the path/url without trailing slash */ function no_trailing_slash( $path ) { if ( substr( $path, -1 ) == '/' ) { return substr( $path, 0, strlen( $path ) - 1); } else { return $path; } } /** * Add a trailing slash, if none present * * @param string the path/url * @return string the path/url with trailing slash */ function trailing_slash( $path ) { if ( empty($path) || substr( $path, -1 ) == '/' ) { return $path; } else { return $path . '/'; } } |
Обратите внимание, что т.к. результатом является строка без терминального слеша, то для корневого пути функция возвращает пустую строку.
Иронично, что эту функцию я выковырял из какого-то заброшенного проекта (не обновлявшегося с 2009 года — https://github.com/LFSF/oras). Назначение архива мне не известно, но пригодилась данная функция. Я её немного причесал и адаптировал, чтобы она работала не только с директориями, но и с файлами. Спасибо тебе, неизвестный автор :).