role IO

Input/output related routines

The role provides no methods, but exists so that IO() coercers, which coerce to IO::Path, correctly type-check the resultant value. The role is done by IO::Path and IO::Special.

Routines

sub chdir

Defined as:

sub chdir(IO() $path:$d = True:$r:$w:$x --> IO::Path:D)

Changes value of $*CWD variable to the provided $path, optionally ensuring the new path passes several file tests. NOTE: that this routine does NOT alter the process's current directory (see &*chdir).

Returns IO::Path representing new $*CWD on success. On failure, returns Failure and leaves $*CWD untouched. The $path can be any object with an IO method that returns an IO::Path object. The available file tests are:

By default, only :d test is performed.

    chdir         '/tmp'# change $*CWD to '/tmp' and check its .d is True 
    chdir :r:w'/tmp'# … check its .r and .w are True 
    chdir '/not-there';   # returns Failure 

Note that the following construct is a mistake:

    # WRONG! DO NOT DO THIS! 
    my $*CWD = chdir '/tmp/';

Use indir instead.

sub &*chdir

Defined as:

    PROCESS:<&chdir> = sub (IO() $path --> IO::Path:D)

Changes value of $*CWD variable to the provided $path and sets the process's current directory to the value of $path.absolute. NOTE: that in most cases, you want to use chdir routine instead.

Returns IO::Path representing new $*CWD on success. On failure, returns Failure and leaves $*CWD untouched. The $path can be any object with an IO method that returns an IO::Path object.

Note that unlike regular chdir, there are no arguments to specify which file tests to perform.

    &*chdir('/tmp');  # change $*CWD and process's current directory to '/tmp' 
    &*chdir('/not-there'); # returns Failure 

Note that the following construct is a mistake:

    # WRONG! DO NOT DO THIS! 
    my $*CWD = &*chdir('/tmp');

Use the following, instead; or see indir if you do not need to change process's current directory:

    temp $*CWD;
    &*chdir('/tmp');

sub chmod

Defined as:

sub chmod(Int() $mode*@filenames --> List)

Coerces all @filenames to IO::Path and calls IO::Path.chmod with $mode on them. Returns a List containing a subset of @filenames for which chmod was successfully executed.

chmod 0o755, <myfile1  myfile2># make two files executable by the owner 

sub indir

Defined as:

sub indir(IO() $path&code:$d = True:$r:$w:$x --> Mu)

Takes Callable &code and executes it after locally (to &code) changing $*CWD variable to $path, optionally ensuring the new path passes several file tests. NOTE: that this routine does NOT alter the process's current directory (see &*chdir). The $*CWD outside of the &code is not affected, even if &code explicitly assigns a new value to $*CWD.

Returns the return value of &code on success. On failure to successfully change $*CWD, returns Failure. WARNING: keep in mind that lazily evaluated things might end up NOT having the $*CWD set by indir in their dynamic scope by the type they're actually evaluated. Either ensure the generators have their $*CWD set or eagerly evaluate them before returning the results from indir:

say indir("/tmp"{
    gather { take ".".IO }
}.CWD# OUTPUT: «(/home/camelia)␤» 
 
say indir("/tmp"{
    eager gather { take ".".IO }
}.CWD# OUTPUT: «(/tmp)␤» 
 
say indir("/tmp"{
    my $cwd = $*CWD;
    gather { temp $*CWD = $cwdtake ".".IO }
}.CWD# OUTPUT: «(/tmp)␤» 

The routine's $path argument can be any object with an IO method that returns an IO::Path object. The available file tests are:

By default, only :d test is performed.

say $*CWD;                   # OUTPUT: «"/home/camelia".IO␤» 
indir '/tmp'{ say $*CWD }# OUTPUT: «"/tmp".IO␤» 
say $*CWD;                   # OUTPUT: «"/home/camelia".IO␤» 
 
indir '/not-there'{;};     # returns Failure; path does not exist 

sub print

Print the given text on $*OUT (standard output), e.g.:

print "Hi there!\n";   # Hi there! 

Note that the print function does not (in contrast to some other languages) append a newline character to the text. Thus the following code

print "Hi there!";
print "How are you?";
print (0..101).list;

displays

Hi there!How are you?0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101

To print text implicitly including the trailing newline character, use put.

sub put

Print the given text on $*OUT (standard output) with appended $*OUT.nl-out. The default for the latter is the platform dependent newline sequence.

put 'Merry 1.0!';
put (0..101).list;

outputs

Merry 1.0!
0 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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

sub say

Print the given text in human readable form, followed by a $*OUT.nl-out (platform dependent newline) on $*OUT (standard output). Long output may be truncated. For machine readable output use put.

With say, the example code as mentioned in the print section will be displayed as the user likely intended:

say "Hi there!";
say "How are you?";
say (0..101).list;

displays

Hi there!
How are you?
(0 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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 ...)␤

say prints non-Str objects by calling their .gist method before printing. Hence the following say statements for the respective containers are equivalent:

my @array = qw{1 2 3 4};
say @array;       # OUTPUT: «[1 2 3 4]␤» 
say @array.gist;  # OUTPUT: «[1 2 3 4]␤» 
 
my %hash = "a" => 1"b" => 2"c" => 3;
say %hash;        # OUTPUT: «{a => 1, b => 2, c => 3}␤» 
say %hash.gist;   # OUTPUT: «{a => 1, b => 2, c => 3}␤» 

routine note

Defined as:

method note(Mu: -->Bool:D)
multi sub note(            --> Bool:D)
multi sub note(Str:D $note --> Bool:D)
multi sub note(**@args     --> Bool:D)

Like say, except prints output to $*ERR handle (STDERR). If no arguments are given to subroutine forms, will use string "Noted".

    note;       # STDERR OUTPUT: «Noted␤» 
    note 'foo'# STDERR OUTPUT: «foo␤» 
    note 1..*;  # STDERR OUTPUT: «1..Inf␤» 

sub prompt

multi prompt()
multi prompt($msg)

Prints $msg to $*OUT handle, if $msg was provided, then gets a line of input from $*IN handle. By default, this is equivalent to printing $msg to STDOUT, reading a line from STDIN, removing the trailing new line, and returning the resultant string.

my $name = prompt "What's your name? ";
say "Hi, $name! Nice to meet you!";

sub open

my $fh = open(IO::Path() $path:$r:$w:$a:$rw,
              :$bin:$enc:$nl-in:$nl-out:$chomp)

Opens the $path (by default in text mode) with the given options, returning an IO::Handle object. In order to close the IO::Handle one needs to call close explicitly or use a LEAVE phaser.

File mode options

Open the file as read only, e.g.:

my $fh = open("path/to/file":r);

This is the default mode for open.

Write-related methods on the returned IO::Handle object will fail in this mode:

my $fh = open("test");   # the file "test" already exists 
$fh.print("new text\n"); # fails 
CATCH { default { put .^name''.Str } };
# OUTPUT: «X::AdHoc: Failed to write bytes to filehandle: bad file descriptor␤» 

Open the file for writing, creating it if it doesn't exist or overwriting the file if it does exist, e.g.:

my $fh = open("path-to-file":w);

Read-related methods will fail in this mode:

my $fh = open("test":w);
$fh.print("stuff\n");
$fh.print("more stuff\n");
$fh.seek(0);      # return to the start of the file 
$fh.get();        # fails 
CATCH { default { put .^name''.Str } };
# OUTPUT: «Reading from filehandle failed: bad file descriptor␤» 

Open the file for reading and writing, creating the file if it doesn't exist or overwriting the file if it already exists.

my $fh = open("path-to-file":rw);

Open the file for appending. If the file does not exist, create it. If the file already exists, append data to it.

my $fh = open("path-to-file":a);

Encoding options

Open the file in binary mode (byte mode):

my $fh = open("path-to-file":bin);

A file opened with :bin may still be processed line-by-line, but IO will be in terms of Buf rather than Str types. Default is False, implying text semantics.

The encoding to use if opened in text mode.

my $fh1 = open 'path-to-file';                # default, utf-8 
my $fh2 = open 'path-to-file':enc<latin-1># explicit, latin-1 

Defaults to utf8. The values are case-insensitive. The available encodings vary by implementation and backend. On Rakudo MoarVM the following are supported:

  utf8
  utf16
  utf8-c8
  iso-8859-1
  windows-1252
  ascii

Implementation may choose to also provide support for aliases, e.g. Rakudo allows aliases latin-1 for iso-8859-1 encoding and dashed utf versions: utf-8 and utf-16.

Newline options

nl-in is the marker used to indicate the end of a line of text. Only used in text mode. Defaults to ["\n", "\r\n"] and does not include "\r". nl-out defaults to "\n".

# explicitly use CR-LF as EOL character 
my $fh = open("path-to-file"nl-in => "\r\n");

Whether or not to remove newline characters from text obtained with .lines and .get. Defaults to True.

# don't remove newline characters from input 
my $fh = open("path-to-file"chomp => False);
say $fh.get();     # returns line including newline char 

sub slurp

Slurps the contents of the entire file into a Str (or Buf if :bin). Accepts :bin and :enc optional named parameters, with the same meaning as open(). The routine will fail if the file does not exist, or is a directory.

# read entire file as (Unicode) Str 
#my $text_contents   = slurp "path-to-file"; 
 
# read entire file as Latin1 Str 
#my $text_contents   = slurp "path-to-file", enc => "latin1"; 
 
# read entire file as Buf 
#my $binary_contents = slurp "path-to-file", :bin; 

sub spurt

Defined as:

multi spurt(IO() $path|c)

The $path can be any object with an IO method that returns an IO::Path object. Calls IO::Path.spurt on the $path, forwarding any of the remaining arguments.

Options

The encoding with which the contents will be written.

Open the file in binary mode.

Boolean indicating whether to append to a (potentially) existing file. If the file did not exist yet, it will be created. Defaults to False.

Boolean indicating whether to fail if the file already exists. Defaults to False.

Examples

# write directly to a file 
#spurt "path/to/file", "default text, directly written"; 
 
# write directly with a non-Unicode encoding 
#spurt "path/to/latin1_file", "latin1 text: äöüß", enc => "latin1"; 
 
# append to a pre-existing file 
#spurt "file_already_exists", "some text"; 
#spurt "file_already_exists", "new text", :append; 
#slurp "file_already_exists";   # some text␤new text 
 
# fail when writing to a pre-existing file 
#spurt "file_already_exists", "new text", :createonly; 
CATCH { default { put .^name''.Str } };
# OUTPUT: «X::Cannot::Empty: Cannot pop from an empty Array␤» 

sub run

sub run(*@args ($*@) --> Proc)

Runs an external command without involving a shell and returns a Proc object.

run 'touch''>foo.txt';
 
run Q:w{rm >foo.txt}# Another way to use run, using word quoting for the 
                      # arguments 

To capture output you can use the :out argument:

my $proc = run 'echo''Perl 6 is Great!':out;
say $proc.out.get# OUTPUT: Perl 6 is Great! 

See Proc and Proc::Async for more details.

sub shell

sub shell($cmd --> Proc)

Runs a command through the system shell. All shell meta characters are interpreted by the shell, including pipes, redirects, environment variable substitutions and so on. Shell escapes are a severe security concern and can cause confusion with unusual file names. Use run if you want to be safe.

The return value is of type Proc.

shell 'ls -lR | gzip -9 > ls-lR.gz';

See Proc for more details, for example on how to capture output.

Related classes

See also the related classes IO::Handle and IO::Path.

Type graph

Type relations for IO
perl6-type-graph IO IO Mu Mu Any Any Any->Mu IO::Special IO::Special IO::Special->IO IO::Special->Any Cool Cool Cool->Any IO::Path IO::Path IO::Path->IO IO::Path->Cool IO::Path::Win32 IO::Path::Win32 IO::Path::Win32->IO::Path IO::Path::Cygwin IO::Path::Cygwin IO::Path::Cygwin->IO::Path IO::Path::QNX IO::Path::QNX IO::Path::QNX->IO::Path IO::Path::Unix IO::Path::Unix IO::Path::Unix->IO::Path

Stand-alone image: vector