#!/bin/sh : <<=cut =pod =head1 NAME marks - a tool for marking and acting on file paths =head1 SYNOPSIS marks add # Add a file path to the mark list marks + # Shorthand for add marks remove # Remove a file path from the mark list marks - # 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 # 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 is a convenience shorthand for C. =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 or other commands which expect null-terminated file lists. Analogous to C. 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. 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" "$@"