#!/usr/bin/env perl use v5.24; use strict; use warnings; use File::Basename; use Try::Tiny; use List::Util 'uniq'; use Net::DBus; # you probably want /etc/udev/rules.d/88-udisks2.rules with: # # SUBSYSTEM=="block", ENV{UDISKS_FILESYSTEM_SHARED}="1" # # so everything is mounted under /media instead of /run/media/$USER/ my $bus = Net::DBus->system(); my $srv = $bus->get_service('org.freedesktop.UDisks2'); my $ud = $srv->get_object('/org/freedesktop/UDisks2/Manager'); sub filter_dev { my ($device_path) = @_; my $dev = $srv->get_object($device_path); return unless $dev->_net_dbus_introspector->has_interface('org.freedesktop.UDisks2.Filesystem'); my $ignore = try { $dev->HintIgnore } catch { 1 }; return if $ignore; my $mounted = try { $dev->MountPoints->@* } catch { 1 }; return if $mounted; return $dev; } sub list { return map { $_->IdLabel || $_->IdUUID } map { filter_dev($_) } @{$ud->GetBlockDevices({})}; } sub mount { my ($name) = @_; my @devs = map { filter_dev($_) } uniq( @{$ud->ResolveDevice({label=>$name},{})}, @{$ud->ResolveDevice({uuid=>$name},{})}, ); die "No device matching '$name'\n" unless @devs; $_->Mount({}) for @devs; } my $cmd = basename($0); if (!@ARGV) { warn <<"EOF"; $cmd # mount $cmd --list # list names $cmd --bashcomp # print completion code EOF exit 1; } elsif ($ARGV[0] eq '--list') { say for list(); } elsif ($ARGV[0] eq '--bashcomp') { print <<"EOF"; _dmount_list() { COMPREPLY=( $( compgen -W '\$($cmd --list)' -- "\$2" ) ) } complete -F _dmount_list $cmd EOF } else { mount($ARGV[0]); }