NAME
    File::Trash::FreeDesktop - Trash files

VERSION
    This document describes version 0.207 of File::Trash::FreeDesktop (from
    Perl distribution File-Trash-FreeDesktop), released on 2023-11-21.

SYNOPSIS
     use File::Trash::FreeDesktop;

     my $trash = File::Trash::FreeDesktop->new;

     # list available (for the running user) trash directories
     my @trashes = $trash->list_trashes;

     # list the content of a trash directory
     my @content = $trash->list_contents("/tmp/.Trash-1000");

     # list the content of all available trash directories
     my @content = $trash->list_contents;

     # trash a file
     $trash->trash("/foo/bar");

     # specify some options when trashing
     $trash->trash({on_not_found=>'ignore'}, "/foo/bar");

     # recover a file from trash (untrash)
     $trash->recover('/foo/bar');

     # untrash a file from a specific trash directory
     $trash->recover('/tmp/file', '/tmp/.Trash-1000');

     # specify some options when untrashing
     $trash->recover({on_not_found=>'ignore', on_target_exists=>'ignore'}, '/path');

     # empty a trash directory
     $trash->empty("$ENV{HOME}/.local/share/Trash");

     # empty all available trashes
     $trash->empty;

DESCRIPTION
    This module lets you trash/erase/restore files, also list the contents
    of trash directories. This module follows the freedesktop.org trash
    specification [1], with some notes/caveats:

    *   For home trash, $HOME/.local/share/Trash is used instead of
        $HOME/.Trash

        This is what KDE and GNOME use these days.

    *   Symlinks are currently not checked

        The spec requires implementation to check whether trash directory is
        a symlink, and refuse to use it in that case. This module currently
        does not do said checking.

    *   Currently cross-device copying is not implemented/done

        It should not matter though, because trash directories are
        per-filesystem.

    Keywords: recycle bin

THE TRASH STRUCTURE
    The following is a short description of the trash structure.

    A trash directory is a per-filesystem, per-user directory structure to
    allow files to be "trashed", i.e. to be put inside and to be recovered
    to its original location later should a user changes his/her mind and
    wants the files back. Otherwise, user can "empty" the trash to delete
    files permanently.

    A trash directory, e.g. "/home/USER1/.local/share/Trash", contains two
    subdirectories: "info" and "files". The "files" contain the actual
    trashed files and their name must be unique. Thus if
    "/home/USER1/foo.txt" is trashed and then another "/home/USER1/foo.txt"
    is trashed again, the second file must be renamed to "/home/USER1/foo
    (1).txt" or something else.

    The "info" subdirectory contains the metadata for each trashed file,
    with each metadata put in an INI of the same name of the correspoonding
    file in "files" with ".trashinfo" suffix, under the INI "Trash Info"
    section. Known INI parameters include: "Path" (the original name/path of
    the trashed file) and "DeletionDate" (date and time, in ISO8601 format).

NOTES
    Weird scenario: /PATH/.Trash-UID is mounted on its own scenario? How
    about /PATH/.Trash-UID/{files,info}.

METHODS
  $trash = File::Trash::FreeDesktop->new(%opts)
    Constructor.

    Known options:

    *   home_only

        Bool. If set to true, instruct the module to just look for trash
        directory under the home directory and not search other filesystem
        mountpoints for possible trash directories.

  $trash->list_trashes() => LIST
    List user's existing trash directories on the system.

    Return a list of trash directories. Sample output:

     ("/home/mince/.local/share/Trash",
      "/tmp/.Trash-1000")

  $trash->list_contents([ \%opts ], [ $trash_dir ]) => LIST
    List contents of trash director(y|ies).

    If $trash_dir is not specified, list contents from all existing trash
    directories. Die if $trash_dir does not exist or inaccessible or
    corrupt. Return a list of records like the sample below:

     ({entry=>"file1", path=>"/home/mince/file1", deletion_date=>1342061508,
       trash_dir=>"/home/mince/.local/share/Trash"},
      {entry=>"file1.2", path=>"/home/mince/sub/file1", deletion_date=>1342061580,
       trash_dir=>"/home/mince/.local/share/Trash"},
      {entry=>"dir1", path=>"/tmp/dir1", deletion_date=>1342061510,
       trash_dir=>"/tmp/.Trash-1000"})

    The "path" key is the original path of the file before it is put into
    the trash.

    Known options:

    *   suffix

        Str.

    *   path_wildcard

        Wildcard pattern to be matched against path. Only matching entries
        will be returned.

    *   path_re

        Regexp pattern to be matched against path. Only matching entries
        will be returned.

    *   path

        Exact matching against path. Only matching entries will be returned.

    *   filename_wildcard

        Wildcard pattern to be matched against the filename part of path.
        Only matching entries will be returned.

    *   filename_re

        Regexp pattern to be matched against the filename part of path. Only
        matching entries will be returned.

    *   filename

        Exact matching against filename part of path. Only matching entries
        will be returned.

    *   mtime

        Int. Only return entries where the trashed file's modification time
        matches this <value.

  $trash->trash([\%opts, ]$file) => STR
    Trash a file (move it into trash dir).

    Will try to find a trash dir that resides in the same filesystem/device
    as the file and is writable. "$home/.local/share/Trash" is tried first,
    then "$device_root/.Trash-$uid", then "$device_root/tmp/.Trash-$uid".
    Will die if no suitable trash dir is found.

    Will also die if moving file to trash (currently using rename()) fails.

    Upon success, will return the location of the file in the trash dir
    (e.g. "/tmp/.Trash-1000/files/foo").

    If first argument is a hashref, it will be accepted as options. Known
    options:

    *   on_not_found => STR (default 'die')

        Specify what to do when the file to be deleted is not found. The
        default is 'die', but can also be set to 'ignore' and return
        immediately.

    *   suffix => STR

        Pick a suffix. Normally, file will be stored in "files/ORIGNAME"
        inside trash directory, or, if that file already exists, in
        "files/ORIGNAME.1", "files/ORIGNAME.2", and so on. This setting
        overrides this behavior and picks "files/ORIGNAME.SUFFIX". Can be
        used to identify and restore particular file later. However, will
        die if file with that suffix already exists, so be sure to pick a
        unique suffix.

  $trash->recover([\%opts, $orig_path, $trash_dir])
    Recover a file or multiple files from trash.

    Unless $trash_dir is specified, will search in all existing user's trash
    dirs. Will die on errors.

    You need to specify the original path of the file before it was trashed,
    but you can also specify unqualified filename (without path) and/or path
    patterns via options (see below) instead.

    If no files are found, the method will simply return.

    If first argument is a hashref, it will be accepted as options. Known
    options:

    *   filename

        See list_contents().

    *   filename_wildcard

        See list_contents().

    *   filename_re

        See list_contents().

    *   path

        See list_contents().

    *   path_wildcard

        See list_contents().

    *   path_re

        See list_contents().

    *   mtime

        See list_contents().

    *   on_target_exists => STR (default 'die')

        Specify what to do when restore target already exists. The default
        is 'die', but can also be set to 'ignore' and return immediately.

    *   mtime => INT

        Only recover file if file's mtime is the one specified. This can be
        useful to make sure that the file we recover is really the one that
        we trashed earlier, especially if we trash several files with the
        same path.

        (Ideally, instead of mtime we should use some unique ID that we
        write in the .trashinfo file, but I fear that an extra parameter in
        .trashinfo file might confuse other implementations.)

        See also "suffix", which is the recommended way to identify and
        recover particular file.

    *   suffix => STR

        Only recover file having the specified suffix, chosen previously
        during trash().

  $trash->erase([ \%opts, ] $file[, $trash_dir]) => LIST
    Erase (unlink()) a file or multiple files in trash.

    Unless $trash_dir is specified, will empty all existing user's trash
    dirs. Will ignore if file does not exist in trash. Will die on errors.

    To erase multiple files based on wilcard or regexp pattern, use the
    options. See list_contents().

    Return list of files erased.

  $trash->empty([$trash_dir]) => LIST
    Empty trash.

    Unless $trash_dir is specified, will empty all existing user's trash
    dirs. Will die on errors.

    Return list of files erased.

ENVIRONMENT
  PERL_FILE_TRASH_FREEDESKTOP_DEBUG
    Bool, if set to true will produce additional logging statements using
    Log::ger at the "trace" level.

HOMEPAGE
    Please visit the project's homepage at
    <https://metacpan.org/release/File-Trash-FreeDesktop>.

SOURCE
    Source repository is at
    <https://github.com/perlancar/perl-File-Trash-FreeDesktop>.

SEE ALSO
  Specification
    <https://freedesktop.org/wiki/Specifications/trash-spec>

  CLI utilities
    *   App::TrashUtils

        A set of CLI's written in Perl: trash-empty, trash-list,
        trash-list-trashes, trash-put, trash-restore, trash-rm.

    *   trash-u (from App::trash::u)

        An alternative CLI, with undo support.

    *   trash-cli

        A set of CLI's written in Python: "trash-empty", "trash-list",
        "trash-put", "trash-restore", "trash-rm".

        <https://github.com/andreafrancia/trash-cli>

  Related CPAN modules
    *   Trash::Park

        Different trash structure (a single CSV file per trash to hold a
        list of deleted files, files stored using original path structure,
        e.g. "home/dir/file"). Does not create per-filesystem trash.

    *   File::Trash

        Different trash structure (does not keep info file, files stored
        using original path structure, e.g. "home/dir/file"). Does not
        create per-filesystem trash.

    *   File::Remove

        File::Remove includes the trash() function which supports Win32, but
        no undeletion function is provided at the time of this writing.

AUTHOR
    perlancar <perlancar@cpan.org>

CONTRIBUTOR
    Steven Haryanto <stevenharyanto@gmail.com>

CONTRIBUTING
    To contribute, you can send patches by email/via RT, or send pull
    requests on GitHub.

    Most of the time, you don't need to build the distribution yourself. You
    can simply modify the code, then test via:

     % prove -l

    If you want to build the distribution (e.g. to try to install it locally
    on your system), you can install Dist::Zilla,
    Dist::Zilla::PluginBundle::Author::PERLANCAR,
    Pod::Weaver::PluginBundle::Author::PERLANCAR, and sometimes one or two
    other Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps
    required beyond that are considered a bug and can be reported to me.

COPYRIGHT AND LICENSE
    This software is copyright (c) 2023, 2017, 2015, 2014, 2012 by perlancar
    <perlancar@cpan.org>.

    This is free software; you can redistribute it and/or modify it under
    the same terms as the Perl 5 programming language system itself.

BUGS
    Please report any bugs or feature requests on the bugtracker website
    <https://rt.cpan.org/Public/Dist/Display.html?Name=File-Trash-FreeDeskto
    p>

    When submitting a bug or request, please include a test-file or a patch
    to an existing test-file that illustrates the bug or desired feature.