Another pipe menu for recursive directory listing. I tried to keep the
code as simple and short as possible. It uses Perl's <File::Find> to
get the directories and files in the current directory and lists them in
alphabetic order while making each directory a submenu. It escapes
special characters and prints the underscore correctly (unlike obbrowser).
You can adjust options such as starting directory, show hidden files,
show '..', show bookmarks (can handle any URL, not just local files) and
bookmark file location.
#!/usr/bin/perl# Openbox menu to recursively list directories and files.useFile::Basename;useFile::Find::Rule;useCwd'abs_path';useFile::Spec::Functionsqw/ catdir catfile /;usewarnings;usestrict;subsay{print"$_\n"for@_;}subprint_browse;subprint_bookmarks;subitem;submenu;subfix_html(\$);############################################################################################################################################ CONFIGURATION ############################################################################################################################################ set default starting directorymy $base_dir = '/';# true to show hidden files and directoriesmy $show_hidden = 1;# true to show ..my $show_up = 0;# true to show gtk bookmarks at the top of the root menumy $show_bookmarks = 1;# file from which to read bookmarksmy $gtk_bookmarks_file = "$ENV{HOME}/.gtk-bookmarks";# show 'Open in browser' entrymy $browse = 1;################################################################################################### path to this script needed because it calls itself to list subdirectoriesmy $path = abs_path $0;# when listing subdirectories, set the starting dir accordingly$base_dir = abs_path $ARGV[0] if $ARGV[0];say "<openbox_pipe_menu>";print_browse if $browse;print_bookmarks if $show_bookmarks && ! $ARGV[0];if ( $show_up && $base_dir ne '/' ) { # replace some special characters by their html codes my $parent = dirname $base_dir; fix_html $parent; menu "$parent/", '..', $parent;}for ( sort { lc $a cmp lc $b } File::Find::Rule ->relative ->maxdepth( 1 ) ->directory ->name( $show_hidden ? qr/.*/ : qr/^[^.].*/ ) ->in( $base_dir )) { # replace some special characters by their html codes my $dir = catdir($base_dir, $_); fix_html $dir; fix_html $_; # replace the underscore with a double underscore in the label to # prevent openbox from interpreting it as a keyboard accelerator $_ =~ s/_/__/g; # escape special characters in bash $dir =~ s/(\ |'|`|!|\^|&|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g; menu $dir, $_, $dir;}for ( sort { lc $a cmp lc $b } File::Find::Rule ->relative ->maxdepth( 1 ) ->file() ->name( $show_hidden ? qr/.*/ : qr/^[^.].*/ ) ->in( $base_dir )) { # replace some special characters by their html codes my $file = catfile($base_dir, $_); fix_html $file; fix_html $_; # replace the underscore with a double underscore in the label to # prevent openbox from interpreting it as a keyboard accelerator $_ =~ s/_/__/g; # escape special characters in bash $file =~ s/(\ |'|`|!|\^|&|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g; item $_, $file;}say "</openbox_pipe_menu>";exit 0;############################################################################################################################################# SUBROUTINES ############################################################################################################################################sub print_browse { my $dir = shift || $base_dir; # replace some special characters by their html codes fix_html $dir; # escape special characters in bash $dir =~ s/(\ |'|`|!|\^|&|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g; item "Openinbrowser", $dir; say "<separator/>";}sub print_bookmarks { open GTK_BKM, '<', $gtk_bookmarks_file or die "Nosuchfile$gtk_bookmarks_file\n"; while ( <GTK_BKM> ) { chomp; $_ =~ s/^\s+|\s+$//g; # remove leading and trailing spaces next unless $_; # ignore empty lines # cannot have spaces in filenames, even if they are escaped my ($bookmark, $label) = ( $_ =~ m/^([^ ]+)(?:\ (.*)|$)/g ); ## if no label was given take the base name for files ( $label ) = $bookmark =~ m|[^/]+$|g if $bookmark =~ m|^file://| && ! length $label; ## for any other urls, take the whole url $label = $bookmark unless length $label; # replace some special characters by their html codes fix_html $bookmark; fix_html $label; # replace the underscore with a double underscore in the label to # prevent openbox from interpreting it as a keyboard accelerator $label =~ s/_/__/g; # escape special characters in bash $bookmark =~ s/(\ |'|`|!|\^|&|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g; # print menu/item for directories/files and items for any other urls if ( $bookmark =~ s|^file://|| && ( -d $bookmark || -l $bookmark ) ) { menu $bookmark, $label, $bookmark; } else { item $label, $bookmark; } } say "<separator/>"; close GTK_BKM;}# print a menu for directorysub menu { my $id = shift; my $label = shift; my $dir = shift; say "<menuid=\"$id\" label=\"$label\" execute=\"$path $dir\" />";}# print an itemsubitem{my$label=shift;my$file=shift;say" <item label=\"$label\">";say" <action name=\"Execute\">";say" <execute>";say" xdg-open $file";say" </execute>";say" </action>";say" </item>";}subfix_html(\$) {my$ref=shift;$$ref=~s/&/&/g;$$ref=~s/"/"/g;$$ref=~s/\$/$/g;$$ref=~s/</</g;$$ref=~s/=/=/g;$$ref=~s/>/>/g;$$ref=~s/\\/\/g;}