A utility to mark and operate on files in the shell.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

137 lines
3.9 KiB

#!/bin/sh
: <<=cut
=pod
=head1 NAME
marks - a tool for marking and acting on file paths
=head1 SYNOPSIS
marks add <path> # Add a file path to the mark list
marks + <path> # Shorthand for add
marks remove <path> # Remove a file path from the mark list
marks - <path> # Shorthand for remove
marks clear # Remove all marks from list
marks ls # List current marks
marks cp # Copy marked files to current directory
marks mv # Move files to current directory and unmark
marks each <command> # Execute command with each marked file as parameter
marks -h # Print help message
=head1 DESCRIPTION
marks stores a list of marked file paths in an SQLite database called marks.db
in the user's home directory. Once marked, files can be copied, moved, listed,
or passed as parameters to arbitrary shell commands.
Commands are intended to be invoked as subcommands of mark(1), in the style of
git(1).
=head1 COMMANDS
=head2 marks-add, marks +
Add one or more paths to the mark list. Relative paths will be stored by their
absolute location. Repeated commands are idempotent - a path can only appear
once in the mark list.
C<marks +> is a convenience shorthand for C<marks add>.
=head2 mark-remove
Remove one or more paths from the mark list. Relative paths will be resolved
to their absolute location before the list is searched.
=head2 marks-clear
Clear the entire mark list.
=head2 marks-ls
List all currently marked paths, one line per path.
=head2 marks-ls --print0
List all currently marked paths, separated by null characters, for use when
piping to C<xargs -0> or other commands which expect null-terminated file
lists. Analogous to C<find -print0>. This is useful where filenames contain
whitespace, quotes, etc.
=head2 marks-cp
Copy all marked paths to the current working directory.
=head2 marks-mv
Move all marked paths to the current working directory, and remove them from
the mark list.
=head2 marks-each
Execute the provided command once per marked path, with the path as a
parameter, and print any output from the command.
This is crudely analogous to C<xargs>. While good enough for simple commands,
it's likely to break in more complex cases, and may be slow for large mark
lists. Consider using marks-ls --print0 and xargs(1) instead.
=head1 SEE ALSO
App::MarkFiles
=head1 LICENSE
marks is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2 of the License.
=head1 AUTHOR
Brennen Bearnes
=cut
print_help() {
echo "$0 - mark and operate on files"
echo
echo "Usage: marks [command] [args]"
echo " marks - List current marks (shortcut for mark ls)"
echo " marks add [path] - Add a file path to the mark list"
echo " marks + [path] - Shorthand for add"
echo " marks remove [path] - Remove a file path from the mark list"
echo " marks - [path] - Shorthand for remove"
echo " marks clear - Clear mark list"
echo " marks cp - Copy marked files to current directory"
echo " marks each [cmd] - Execute command for each marked file"
echo " marks ls - List current marks"
echo " marks mv - Move files to current directory and unmark"
echo " marks -h - Print this help message"
}
if [ $# -lt 1 ]; then
# No arguments - let's just list the existing marks:
exec mark-ls
elif [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
print_help
exit 0
elif [ "$1" = '+' ]; then
subprog="marks-add"
elif [ "$1" = '-' ]; then
subprog="marks-remove"
else
subprog="marks-$1"
fi
# Make sure that the subcommand we're trying to run exists:
command -v "$subprog" >/dev/null 2>&1 || {
echo "marks: '$1' is not a marks command."
echo
print_help
exit 1
}
# Get rid of subcommand name from arguments:
shift
exec "$subprog" "$@"