Use gio for Safe File Operations and GIO Locations
You will finish with a small, repeatable set of gio commands for inspecting and moving files, saving standard input, watching a directory and using locations such as smb://server/share. The examples match GLib 2.86.4, provided here by package libglib2.0-bin version 2.80.0-6ubuntu3.9.
The route
Jump straight to the step you need, or tick off Done means at the end.
- 1. Confirm the installed command
- 2. Inspect a location before changing it
- 3. Copy a file, then verify the result
- 4. Move or rename a file
- 5. Save standard input without a local shell redirect
- 6. Use the trash for reversible removal
- 7. Monitor changes without polling
- 8. Handle applications and mounts carefully
Allow about fifteen minutes. You need a shell and the libglib2.0-bin package. The examples use a temporary directory and do not need sudo. If you work with a mounted device, a protected directory or a remote service, authentication or extra permissions may be required, but adding elevated privileges does not fix an incorrect location or a missing GIO backend.
1. Confirm the installed command
Start by checking the binary and the GLib version. This is read-only:
$ command -v gio
/usr/bin/gio
$ gio version
2.86.4
$ gio help list
The version command reports the GLib version to which gio belongs. Use gio help COMMAND when you need the option spelling supported by this installation, for example gio help save or gio help monitor.
Checkpoint
If command -v gio finds nothing, install the package through your normal system management process before continuing. Do not copy a different machine's command path into a script.
2. Inspect a location before changing it
gio accepts GIO locations, not only ordinary local paths. Use info for attributes and list for directory contents:
$ gio info /path/to/file.txt
$ gio list --long /path/to/directory
A local inspection normally includes the display name, type, size, URI, local path and a set of GIO attributes. A long listing shows entries in a compact form, including their size and type. Add --attributes=standard::name,standard::size when a script needs a smaller, more predictable result. Add --print-uris when you need full GIO URIs rather than display names.
There is a small but confusing parsing rule: a plain filename containing a colon is treated as a URI with an unknown scheme. Write ./report:2026.txt or file:///path/to/report:2026.txt when the colon is part of a local filename.
For a recursive view, use:
$ gio tree /path/to/directory
The tree command follows the manual's default behaviour. Use --hidden to include hidden entries, and use --follow-symlinks only when traversing links is deliberate.
3. Copy a file, then verify the result
Copying is an ordinary user operation when both locations are writable:
$ gio copy /path/to/source.txt /path/to/backup.txt
$ gio info /path/to/backup.txt | sed -n '1,8p'
If the destination is an existing directory, the source is copied into it. Use --no-target-directory when the destination must be treated as the exact target rather than as a directory. For a cautious interactive overwrite, add --interactive. Use --backup if retaining the previous destination matters.
gio copy can copy more than one source, but then the destination must be a directory. A failed command returns a non-zero status. Check that status in a script immediately after the operation rather than assuming that a printed command completed successfully.
4. Move or rename a file
Use move for a relocation and rename for changing one name in its existing location:
$ gio move /path/to/backup.txt /path/to/archive/
$ gio rename /path/to/archive/backup.txt backup-verified.txt
$ gio info /path/to/archive/backup-verified.txt | sed -n '1,6p'
Both commands can replace an existing destination in situations supported by the backend. Add --interactive to move when an accidental overwrite would be costly. The move command can fall back to copying and deleting across locations; use --no-copy-fallback when that behaviour is unacceptable for the operation you are testing.
Warning
A move can change state immediately. Keep the source until the destination has been checked, and do not use a production directory as a first test. If the move fails, inspect both locations before retrying so that you do not create an unwanted duplicate.
5. Save standard input without a local shell redirect
save reads standard input and writes it to a GIO location. This is useful when the destination is not a normal local path:
$ printf '%s\n' 'created by gio' | gio save --create /path/to/new-note.txt
$ gio cat /path/to/new-note.txt
created by gio
--create refuses to replace an existing destination. Use --append to add data, --backup to preserve an existing file, or --private when a newly created file should be restricted to the current user. --print-etag reports the new entity tag; --etag lets a backend check that the destination still has the expected tag before replacement.
Shell redirection with > can truncate a local file before the producing command has succeeded. Prefer --create for a new file, or write to a new name and rename it after verification. If a command has already replaced a file, recovery depends on whether you made a backup or whether the remote backend provides version history.
6. Use the trash for reversible removal
Do not begin with gio remove. The manual describes it as irreversible:
$ gio trash /path/to/old-note.txt
$ gio trash --list
Trash is normally stored below $XDG_DATA_HOME/Trash for files in a home directory, although the location depends on the filesystem and backend. Moving a file to the trash does not free its space until the trash is emptied. Restore a listed URI with:
$ gio trash --restore trash://<entry-from-the-list>
Use gio trash --empty only after checking the list and deciding that every entry can be lost. Emptying the trash is destructive and has no general gio undo command. gio remove is for a deliberate irreversible deletion; reserve --force for scripts that have already decided how to handle missing locations.
7. Monitor changes without polling
To watch a directory until you stop it with Ctrl-C, run:
$ gio monitor --directory /path/to/watch
The installed synopsis uses --dir=LOCATION, so the unambiguous form is:
$ gio monitor --dir=/path/to/watch
Events can include creation, deletion, content and attribute changes, and moves. Use --no-moves when a consumer needs separate delete and create events. Use --file=LOCATION to force file monitoring, or --direct=LOCATION when changes through hard links must be captured. The Linux implementation commonly uses inotify, so backend limits and event details still apply. A monitor is not an audit log and should not be your only record of changes.
8. Handle applications and mounts carefully
gio open /path/to/document.pdf asks the desktop's registered default application to open a file. The choice comes from the shared MIME database and per-user overrides. Inspect handlers with gio mime application/pdf. Supplying a desktop file to gio mime changes the default handler, so treat that as a persistent user configuration change and verify the handler name, including its .desktop suffix, first.
gio mount --list lists GIO mounts. Mounting a remote location can prompt for credentials, and gio mount --unmount LOCATION or gio mount --eject LOCATION changes device or session state. Do not place passwords in shell history or scripts. The --force mount option ignores outstanding file operations during unmounting or ejecting; use it only when you understand the risk of interrupting those operations. These commands normally do not need sudo, but access may still be denied by the desktop session, backend or device policy.
Done means
gio versionandgio help COMMANDmatch the installed command.- You inspected a location before copying, moving or saving to it.
- Local filenames containing colons were made unambiguous with
./orfile:. - New or replaced files were protected with
--create, backups or a post-operation check where appropriate. - You used
trashfor reversible removal and understand thatremoveis irreversible. - Monitoring, MIME changes and mounts are treated as separate operations with their own state and security boundaries.