1 /** 2 * ae.utils.path 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <vladimir@thecybershadow.net> 12 */ 13 14 module ae.utils.path; 15 16 import std.path; 17 18 /// Modify a path under oldBase to a new path with the same subpath under newBase. 19 /// E.g.: `/foo/bar`.rebasePath(`/foo`, `/quux`) == `/quux/bar` 20 string rebasePath(string path, string oldBase, string newBase) 21 { 22 return buildPath(newBase, path.absolutePath.relativePath(oldBase.absolutePath)); 23 } 24 25 /// Like Pascal's IncludeTrailingPathDelimiter 26 string includeTrailingPathSeparator(string path) 27 { 28 if (path.length && !path[$-1].isDirSeparator()) 29 path ~= dirSeparator; 30 return path; 31 } 32 33 /// Like Pascal's ExcludeTrailingPathDelimiter 34 string excludeTrailingPathSeparator(string path) 35 { 36 if (path.length && path[$-1].isDirSeparator()) 37 path = path[0..$-1]; 38 return path; 39 } 40 41 // ************************************************************************ 42 43 import std.process : environment; 44 import std.string : split; 45 46 @property string[] pathDirs() 47 { 48 return environment["PATH"].split(pathSeparator); 49 } 50 51 bool haveExecutable(string name) 52 { 53 return findExecutable(name, pathDirs) !is null; 54 } 55 56 /// Find an executable with the given name 57 /// (no extension) in the given directories. 58 /// Returns null if not found. 59 string findExecutable(string name, string[] dirs) 60 { 61 import std.file : exists; 62 63 version (Windows) 64 enum executableSuffixes = [".exe", ".bat", ".cmd"]; 65 else 66 enum executableSuffixes = [""]; 67 68 foreach (dir; dirs) 69 foreach (suffix; executableSuffixes) 70 { 71 auto fn = buildPath(dir, name) ~ suffix; 72 if (fn.exists) 73 return fn; 74 } 75 76 return null; 77 } 78 79 80 // ************************************************************************ 81 82 /// The file name for the null device 83 /// (which discards all writes). 84 version (Windows) 85 enum nullFileName = "nul"; 86 else 87 enum nullFileName = "/dev/null";