txt: ## unix.md
  class IO::Spec::Unix
  
  Platform specific operations on file and directory paths for POSIX
  
  ```raku
  class IO::Spec::Unix is IO::Spec  { }
  ```
  
  An object of this type is available via the variable `$*SPEC` if the Raku interpreter is running on a Unix-like platform.
  
  About this class and its related classes also see [`IO::Spec`](/type/IO/Spec).
  
  # [Methods](#class_IO::Spec::Unix "go to top of document")[§](#Methods "direct link")
  
  ## [method abs2rel](#class_IO::Spec::Unix "go to top of document")[§](#method_abs2rel "direct link")
  
  ```raku
  method abs2rel(IO::Path:D $path, IO::Path:D $base = $*CWD --> Str:D)
  ```
  
  Returns a string that represents `$path`, but relative to `$base` path. Both `$path` and `$base` may be relative paths. `$base` defaults to `$*CWD`.
  
  ## [method basename](#class_IO::Spec::Unix "go to top of document")[§](#method_basename "direct link")
  
  ```raku
  method basename(Str:D $path --> Str:D)
  ```
  
  Takes a path as a string and returns a possibly-empty portion after the last slash:
  
  ```raku
  IO::Spec::Unix.basename("foo/bar/") .raku.say; # OUTPUT: «""␤»
  IO::Spec::Unix.basename("foo/bar/.").raku.say; # OUTPUT: «"."␤»
  IO::Spec::Unix.basename("foo/bar")  .raku.say; # OUTPUT: «"bar"␤»
  ```
  
  ## [method canonpath](#class_IO::Spec::Unix "go to top of document")[§](#method_canonpath "direct link")
  
  ```raku
  method canonpath(Str() $path, :$parent --> Str:D)
  ```
  
  Returns a string that is a canonical representation of `$path`. If `:$parent` is set to true, will also clean up references to parent directories. **NOTE:** the routine does not access the filesystem, so no symlinks are followed.
  
  ```raku
  IO::Spec::Unix.canonpath("foo//../bar/../ber").say;
  # OUTPUT: «foo/../bar/../ber␤»
  
  IO::Spec::Unix.canonpath("foo///./../bar/../ber").say;
  # OUTPUT: «foo/../bar/../ber␤»
  
  IO::Spec::Unix.canonpath("foo///./../bar/../ber", :parent).say;
  # OUTPUT: «ber␤»
  ```
  
  ## [method catdir](#class_IO::Spec::Unix "go to top of document")[§](#method_catdir "direct link")
  
  ```raku
  method catdir (*@parts --> Str:D)
  ```
  
  Concatenates multiple path fragments and returns the canonical representation of the resultant path as a string. The `@parts` are [`Str`](/type/Str) objects and are allowed to contain path separators.
  
  ```raku
  IO::Spec::Unix.catdir(<foo/bar ber raku>).say; # OUTPUT: «foo/bar/ber/raku␤»
  ```
  
  ## [method catfile](#class_IO::Spec::Unix "go to top of document")[§](#method_catfile "direct link")
  
  Alias for [`catdir`](/routine/catdir).
  
  ## [method catpath](#class_IO::Spec::Unix "go to top of document")[§](#method_catpath "direct link")
  
  ```raku
  method catpath ($, Str:D $part1, Str:D $part2 --> Str:D)
  ```
  
  Takes two path fragments and concatenates them, adding or removing a path separator, if necessary. The first argument is ignored (it exists to maintain consistent interface with other [`IO::Spec`](/type/IO/Spec) types for systems that have volumes).
  
  ```raku
  IO::Spec::Unix.catpath($, 'some/dir', 'and/more').say;
  # OUTPUT: «some/dir/and/more␤»
  ```
  
  ## [method curdir](#class_IO::Spec::Unix "go to top of document")[§](#method_curdir "direct link")
  
  ```raku
  method curdir()
  ```
  
  Returns a string representing the current directory:
  
  ```raku
  say '.' eq $*SPEC.curdir; # OUTPUT: «True␤»
  ```
  
  ## [method curupdir](#class_IO::Spec::Unix "go to top of document")[§](#method_curupdir "direct link")
  
  ```raku
  method curupdir()
  ```
  
  Returns a [`Block`](/type/Block) taking an argument. This block returns `True` if its argument is neither the string representing the current directory nor the string representing the directory one up from the current one. It returns `False` otherwise. This block is intended to be used with [smartmatching](/language/operators#infix_~~).
  
  ```raku
  say $*SPEC.curupdir;
  # OUTPUT: «-> str $dir { #`(Block|65335808) ... }␤»
  
  my @dirs = <. foo .. bar>;
  say @dirs.grep: { $_ ~~ $*SPEC.curupdir };
  # OUTPUT: «(foo bar)␤»
  
  ```
  
  Neither `foo` nor `bar` are equal to the representation of the current or parent directory, that is why they are returned by `grep`.
  
  **Note**: Before Rakudo version 2020.06 a [`none`](/routine/none) [`Junction`](/type/Junction) was returned instead of a [`Block`](/type/Block).
  
  ## [method devnull](#class_IO::Spec::Unix "go to top of document")[§](#method_devnull "direct link")
  
  ```raku
  method devnull(--> Str:D)
  ```
  
  Returns the string `"/dev/null"` representing the ["Null device"](https://en.wikipedia.org/wiki/Null_device):
  
  ```raku
  $*SPEC.devnull.IO.spurt: "foo bar baz";
  
  ```
  
  ## [method dir-sep](#class_IO::Spec::Unix "go to top of document")[§](#method_dir-sep "direct link")
  
  ```raku
  method dir-sep(--> Str:D)
  ```
  
  Returns the string `"/"` representing canonical directory separator character.
  
  ```raku
  IO::Spec::Unix.dir-sep.say; # OUTPUT: «/␤»
  
  ```
  
  ## [method extension](#class_IO::Spec::Unix "go to top of document")[§](#method_extension "direct link")
  
  **NOTE:** Most users would want to use the higher-level routine [`IO::Path.extension`](/type/IO/Path#method_extension) instead of this lower-level version.
  
  ```raku
  method extension(Str:D $path --> Str:D)
  ```
  
  Takes a string representing a base name and returns the characters after the last dot (`"."`), or empty string if no dots are present. The routine makes no attempt to detect path separators and will return everything after the last dot.
  
  ```raku
  $*SPEC.extension('foo.'      ).raku.say;  # OUTPUT: «""␤»
  $*SPEC.extension('foo.txt'   ).raku.say;  # OUTPUT: «"txt"␤»
  $*SPEC.extension('foo.tar.gz').raku.say;  # OUTPUT: «"gz"␤»
  $*SPEC.extension('foo'       ).raku.say;  # OUTPUT: «""␤»
  $*SPEC.extension('bar.foo/foo').raku.say; # OUTPUT: «"foo/foo"␤»
  ```
  
  ## [method is-absolute](#class_IO::Spec::Unix "go to top of document")[§](#method_is-absolute "direct link")
  
  ```raku
  method is-absolute(Str:D $path --> Bool:D)
  ```
  
  Returns `True` if the `$path` starts with a slash (`"/"`), even if it has combining character on it:
  
  ```raku
  say IO::Spec::Unix.is-absolute: "/foo";        # OUTPUT: «True␤»
  say IO::Spec::Unix.is-absolute: "/\x[308]foo"; # OUTPUT: «True␤»
  say IO::Spec::Unix.is-absolute: "bar";         # OUTPUT: «False␤»
  ```
  
  ## [method join](#class_IO::Spec::Unix "go to top of document")[§](#method_join "direct link")
  
  ```raku
  method join ($, Str:D $dir, Str:D $file --> Str:D)
  ```
  
  Similar to [`catpath`](/routine/catpath), takes two path fragments and concatenates them, adding or removing a path separator, if necessary, except it will return just `$file` if both `$dir` and `$file` are string `'/'` or if `$dir` is the string `'.'`. The first argument is ignored (it exists to maintain consistent interface with other [`IO::Spec`](/type/IO/Spec) types for systems that have volumes).
  
  ```raku
  IO::Spec::Unix.join($, 'foo', 'bar').say; # OUTPUT: «foo/bar␤»
  IO::Spec::Unix.join($, '/', '/').say;     # OUTPUT: «/␤»
  IO::Spec::Unix.join($, '.', 'foo').say;   # OUTPUT: «foo␤»
  say $*SPEC.join(True,".","/foo");         # OUTPUT: «/foo␤»
  ```
  
  ## [method path](#class_IO::Spec::Unix "go to top of document")[§](#method_path "direct link")
  
  ```raku
  method path(--> Seq:D)
  ```
  
  Splits the value of `%*ENV<PATH>` on colons (`":"`), replaces empty parts with `"."`, and returns a [`Seq`](/type/Seq) with each of the resultant parts. Returns an empty [`Seq`](/type/Seq) if `%*ENV<PATH>` is not set or is an empty string.
  
  ```raku
  %*ENV<PATH> = 'foo:bar/ber::foo:';
  IO::Spec::Unix.path.raku.say;
  # OUTPUT: «("foo", "bar/ber", ".", "foo", ".").Seq␤»
  ```
  
  ## [method rel2abs](#class_IO::Spec::Unix "go to top of document")[§](#method_rel2abs "direct link")
  
  ```raku
  method rel2abs(Str() $path, $base = $*CWD --> Str:D)
  ```
  
  Returns a string representing `$path` converted to absolute path, based at `$base`, which defaults to `$*CWD`. If `$base` is not an absolute path, it will be made absolute relative to `$*CWD`, unless `$*CWD` and `$base` are the same.
  
  ```raku
  say $*CWD;                                  # OUTPUT: «"/home/camelia".IO␤»
  
  say IO::Spec::Unix.rel2abs: 'foo';          # OUTPUT: «/home/camelia/foo␤»
  say IO::Spec::Unix.rel2abs: './';           # OUTPUT: «/home/camelia␤»
  say IO::Spec::Unix.rel2abs: 'foo/../../';   # OUTPUT: «/home/camelia/foo/../..␤»
  say IO::Spec::Unix.rel2abs: '/foo/';        # OUTPUT: «/foo␤»
  
  say IO::Spec::Unix.rel2abs: 'foo', 'bar';   # OUTPUT: «/home/camelia/bar/foo␤»
  say IO::Spec::Unix.rel2abs: './', '/bar';   # OUTPUT: «/bar␤»
  say IO::Spec::Unix.rel2abs: '/foo/', 'bar'; # OUTPUT: «/foo␤»
  
  say IO::Spec::Unix.rel2abs: 'foo/../../', 'bar';
  # OUTPUT: «/home/camelia/bar/foo/../..␤»
  
  ```
  
  ## [method rootdir](#class_IO::Spec::Unix "go to top of document")[§](#method_rootdir "direct link")
  
  ```raku
  method rootdir(--> Str:D)
  ```
  
  Returns string `'/'`, representing root directory.
  
  ## [method split](#class_IO::Spec::Unix "go to top of document")[§](#method_split "direct link")
  
  ```raku
  method split(IO::Spec::Unix: Cool:D $path)
  ```
  
  Creates an [`IO::Path::Parts`](/type/IO/Path/Parts) for `$path`, with an empty string as its `volume` attribute's value.
  
  ```raku
  IO::Spec::Unix.split('C:/foo/bar.txt').raku.say;
  # OUTPUT: «IO::Path::Parts.new("","C:/foo","bar.txt")␤»
  
  IO::Spec::Unix.split('/foo/').raku.say;
  # OUTPUT: «IO::Path::Parts.new("","/","foo")␤»
  
  IO::Spec::Unix.split('///').raku.say;
  # OUTPUT: «IO::Path::Parts.new("","/","/")␤»
  
  IO::Spec::Unix.split('./').raku.say;
  # OUTPUT: «IO::Path::Parts.new("",".",".")␤»
  
  IO::Spec::Unix.split('.').raku.say;
  # OUTPUT: «IO::Path::Parts.new("",".",".")␤»
  
  IO::Spec::Unix.split('').raku.say;
  # OUTPUT: «IO::Path::Parts.new("","","")␤»
  
  ```
  
  **Note**: Before Rakudo version 2020.06 this method split the given `$path` into "volume", "dirname", and "basename" and returned the result as a [`List`](/type/List) of three [`Pair`](/type/Pair)s, in that order.
  
  ## [method splitdir](#class_IO::Spec::Unix "go to top of document")[§](#method_splitdir "direct link")
  
  ```raku
  method splitdir(Cool:D $path --> List:D)
  ```
  
  Splits the given `$path` on slashes.
  
  ```raku
  IO::Spec::Unix.splitdir('C:\foo/bar.txt').raku.say;
  # OUTPUT: «("C:\\foo", "bar.txt")␤»
  
  IO::Spec::Unix.splitdir('/foo/').raku.say;
  # OUTPUT: «("", "foo", "")␤»
  
  IO::Spec::Unix.splitdir('///').raku.say;
  # OUTPUT: «("", "", "", "")␤»
  
  IO::Spec::Unix.splitdir('./').raku.say;
  # OUTPUT: «(".", "")␤»
  
  IO::Spec::Unix.splitdir('.').raku.say;
  # OUTPUT: «(".",)␤»
  
  IO::Spec::Unix.splitdir('').raku.say;
  # OUTPUT: «("",)␤»
  
  ```
  
  ## [method splitpath](#class_IO::Spec::Unix "go to top of document")[§](#method_splitpath "direct link")
  
  ```raku
  method splitpath(Cool:D $path, :$nofile --> List:D)
  ```
  
  Splits the given `$path` into a list of 3 strings: volume, dirname, and file. The volume is always an empty string, returned for API compatibility with other [`IO::Spec`](/type/IO/Spec) types. If `:$nofile` named argument is set to `True`, the content of the file string is undefined and should be ignored; this is a means to get a performance boost, as implementations may use faster code path when file is not needed.
  
  ```raku
  IO::Spec::Unix.splitpath('C:\foo/bar.txt').raku.say;
  # OUTPUT: «("", "C:\\foo/", "bar.txt")␤»
  
  IO::Spec::Unix.splitpath('C:\foo/bar.txt', :nofile).raku.say;
  # OUTPUT: «("", "C:\\foo/bar.txt", "")␤»
  
  IO::Spec::Unix.splitpath('/foo/').raku.say;
  # OUTPUT: «("", "/foo/", "")␤»
  
  IO::Spec::Unix.splitpath('/foo/', :nofile).raku.say;
  # OUTPUT: «("", "/foo/", "")␤»
  
  IO::Spec::Unix.splitpath('///').raku.say;
  # OUTPUT: «("", "///", "")␤»
  
  IO::Spec::Unix.splitpath('./').raku.say;
  # OUTPUT: «("", "./", "")␤»
  
  IO::Spec::Unix.splitpath('.').raku.say;
  # OUTPUT: «("", "", ".")␤»
  
  IO::Spec::Unix.splitpath('').raku.say;
  # OUTPUT: «("", "", "")␤»
  
  ```
  
  ## [method tmpdir](#class_IO::Spec::Unix "go to top of document")[§](#method_tmpdir "direct link")
  
  ```raku
  method tmpdir(--> IO::Path:D)
  ```
  
  Attempts to locate a system's temporary directory by checking several typical directories and environment variables. Uses current directory if no suitable directories are found.
  
  ## [method updir](#class_IO::Spec::Unix "go to top of document")[§](#method_updir "direct link")
  
  ```raku
  method updir()
  ```
  
  Returns a string representing the directory one up from current:
  
  ```raku
  say '..' eq $*SPEC.updir; # OUTPUT: «True␤»
  ```
  