static void usage_conflicts(void) { usage_header(); puts("Usage: bee dep conflicts\n\n" "Print conflicting packages.\n"); }
static void usage_update(void) { usage_header(); puts("Usage: bee dep update <pkgname>\n\n" "Update the information about a package.\n"); }
static void usage_rebuild(void) { usage_header(); puts("Usage: bee dep rebuild\n\n" "Rebuild the cache.\n"); }
void usage_full(const po::options_description &options, const char* exname) { usage_header(exname); std::cout << "\n Creates groups of files in new directories defined by a metadata 'pattern'.\n" << " Files are copied, moved, or linked from 'source-dir' to 'dest-dir'.\n" << " The destination directory should not be within the source directory.\n\n"; std::cout << options; std::cout << "\nPattern values:\n"; for( const Pattern *pattern = g_patterns; pattern->pat.length(); ++pattern) { std::cout << " " << std::setw(8) << std::left << pattern->pat; std::cout << pattern->desc << "\n"; } std::cout << "\nExamples:\n"; std::cout << " `" << exname << " -m mess clean @year-@month'\n"; std::cout << " Moves files from 'mess' into directories of 'clean' according to\n" << " year-month the file was captured (clean/2006-11/...)\n\n"; std::cout << " `" << exname << " -o ie source find width-@x/height-@y'\n"; std::cout << " Copies files into directories according first to pixel width then pixel\n" << " height. Check iptc then exif metadata (find/width-2272/height-1704/...)\n\n"; std::cout << " `" << exname << " -lf source find @aper/@hour'\n"; std::cout << " Force create symlinks in directories according first to aperture then\n" << " hour captured (find/F3.2/15/...)\n"; std::cout << std::endl; }
static void usage_remove(void) { usage_header(); puts("Usage: bee dep remove [options] <pkgname>\n\n" "Remove a package from the cache.\n\n" "Options:\n" " --print print which files can be deleted from the hard drive\n"); }
static void usage(void) { usage_header(); puts("Usage: bee dep <command> [<args>]\n\n" "Commands:\n" " rebuild rebuild the cache\n" " update update the cache for a specific package\n" " remove remove a package from the cache\n" " list list information\n" " conflicts show conflicting packages\n\n" "See 'bee dep <command> --help' for more information on a specific command."); }
static void usage_list(void) { usage_header(); puts("Usage: bee dep list [options]\n\n" "Get information from the cache.\n\n" "Options:\n" " --packages list all packages\n" " --files <pkg> list all files of a package\n" " --depending-on <pkg|file> list packages depending on a pkg or file\n" " --required-by <pkg|file> list packages required by a pkg or file\n" " --removable <pkg> show all removable files of a package\n" " --provider-of <file> show the providers of a file\n" " --not-cached <file> print files which are not in the cache;\n" " check those files which are listed in <file>\n" " --broken list all broken dependencies\n" " --count do not print results; just count\n"); }
int short_usage(const char *message, ...) { va_list args; if(message) { va_start(args, message); (void) vfprintf(stderr, message, args); va_end(args); } usage_header(stderr); flac_fprintf(stderr, "\n"); flac_fprintf(stderr, "This is the short help; for full help use 'metaflac --help'\n"); flac_fprintf(stderr, "\n"); usage_summary(stderr); return message? 1 : 0; }
int long_usage(const char *message, ...) { FILE *out = (message? stderr : stdout); va_list args; if(message) { va_start(args, message); (void) vfprintf(stderr, message, args); va_end(args); } usage_header(out); fprintf(out, "\n"); usage_summary(out); fprintf(out, "\n"); fprintf(out, "Shorthand operations:\n"); fprintf(out, "--show-md5sum Show the MD5 signature from the STREAMINFO block.\n"); fprintf(out, "--show-min-blocksize Show the minimum block size from the STREAMINFO block.\n"); fprintf(out, "--show-max-blocksize Show the maximum block size from the STREAMINFO block.\n"); fprintf(out, "--show-min-framesize Show the minimum frame size from the STREAMINFO block.\n"); fprintf(out, "--show-max-framesize Show the maximum frame size from the STREAMINFO block.\n"); fprintf(out, "--show-sample-rate Show the sample rate from the STREAMINFO block.\n"); fprintf(out, "--show-channels Show the number of channels from the STREAMINFO block.\n"); fprintf(out, "--show-bps Show the # of bits per sample from the STREAMINFO block.\n"); fprintf(out, "--show-total-samples Show the total # of samples from the STREAMINFO block.\n"); fprintf(out, "\n"); fprintf(out, "--show-vendor-tag Show the vendor string from the VORBIS_COMMENT block.\n"); fprintf(out, "--show-tag=NAME Show all tags where the field name matches 'NAME'.\n"); fprintf(out, "--remove-tag=NAME Remove all tags whose field name is 'NAME'.\n"); fprintf(out, "--remove-first-tag=NAME Remove first tag whose field name is 'NAME'.\n"); fprintf(out, "--remove-all-tags Remove all tags, leaving only the vendor string.\n"); fprintf(out, "--set-tag=FIELD Add a tag. The FIELD must comply with the Vorbis comment\n"); fprintf(out, " spec, of the form \"NAME=VALUE\". If there is currently\n"); fprintf(out, " no tag block, one will be created.\n"); fprintf(out, "--set-tag-from-file=FIELD Like --set-tag, except the VALUE is a filename\n"); fprintf(out, " whose contents will be read verbatim to set the tag value.\n"); fprintf(out, " Unless --no-utf8-convert is specified, the contents will\n"); fprintf(out, " be converted to UTF-8 from the local charset. This can\n"); fprintf(out, " be used to store a cuesheet in a tag (e.g.\n"); fprintf(out, " --set-tag-from-file=\"CUESHEET=image.cue\"). Do not try\n"); fprintf(out, " to store binary data in tag fields! Use APPLICATION\n"); fprintf(out, " blocks for that.\n"); fprintf(out, "--import-tags-from=FILE Import tags from a file. Use '-' for stdin. Each line\n"); fprintf(out, " should be of the form NAME=VALUE. Multi-line comments\n"); fprintf(out, " are currently not supported. Specify --remove-all-tags\n"); fprintf(out, " and/or --no-utf8-convert before --import-tags-from if\n"); fprintf(out, " necessary. If FILE is '-' (stdin), only one FLAC file\n"); fprintf(out, " may be specified.\n"); fprintf(out, "--export-tags-to=FILE Export tags to a file. Use '-' for stdout. Each line\n"); fprintf(out, " will be of the form NAME=VALUE. Specify\n"); fprintf(out, " --no-utf8-convert if necessary.\n"); fprintf(out, "--import-cuesheet-from=FILE Import a cuesheet from a file. Use '-' for stdin.\n"); fprintf(out, " Only one FLAC file may be specified. A seekpoint will be\n"); fprintf(out, " added for each index point in the cuesheet to the\n"); fprintf(out, " SEEKTABLE unless --no-cued-seekpoints is specified.\n"); fprintf(out, "--export-cuesheet-to=FILE Export CUESHEET block to a cuesheet file, suitable\n"); fprintf(out, " for use by CD authoring software. Use '-' for stdout.\n"); fprintf(out, " Only one FLAC file may be specified on the command line.\n"); fprintf(out, "--import-picture-from=FILENAME|SPECIFICATION Import a picture and store it in a\n"); fprintf(out, " PICTURE block. Either a filename for the picture file or\n"); fprintf(out, " a more complete specification form can be used. The\n"); fprintf(out, " SPECIFICATION is a string whose parts are separated by |\n"); fprintf(out, " characters. Some parts may be left empty to invoke\n"); fprintf(out, " default values. FILENAME is just shorthand for\n"); fprintf(out, " \"||||FILENAME\". The format of SPECIFICATION is:\n"); fprintf(out, " [TYPE]|[MIME-TYPE]|[DESCRIPTION]|[WIDTHxHEIGHTxDEPTH[/COLORS]]|FILE\n"); fprintf(out, " TYPE is optional; it is a number from one of:\n"); fprintf(out, " 0: Other\n"); fprintf(out, " 1: 32x32 pixels 'file icon' (PNG only)\n"); fprintf(out, " 2: Other file icon\n"); fprintf(out, " 3: Cover (front)\n"); fprintf(out, " 4: Cover (back)\n"); fprintf(out, " 5: Leaflet page\n"); fprintf(out, " 6: Media (e.g. label side of CD)\n"); fprintf(out, " 7: Lead artist/lead performer/soloist\n"); fprintf(out, " 8: Artist/performer\n"); fprintf(out, " 9: Conductor\n"); fprintf(out, " 10: Band/Orchestra\n"); fprintf(out, " 11: Composer\n"); fprintf(out, " 12: Lyricist/text writer\n"); fprintf(out, " 13: Recording Location\n"); fprintf(out, " 14: During recording\n"); fprintf(out, " 15: During performance\n"); fprintf(out, " 16: Movie/video screen capture\n"); fprintf(out, " 17: A bright coloured fish\n"); fprintf(out, " 18: Illustration\n"); fprintf(out, " 19: Band/artist logotype\n"); fprintf(out, " 20: Publisher/Studio logotype\n"); fprintf(out, " The default is 3 (front cover). There may only be one picture each\n"); fprintf(out, " of type 1 and 2 in a file.\n"); fprintf(out, " MIME-TYPE is optional; if left blank, it will be detected from the\n"); fprintf(out, " file. For best compatibility with players, use pictures with MIME\n"); fprintf(out, " type image/jpeg or image/png. The MIME type can also be --> to\n"); fprintf(out, " mean that FILE is actually a URL to an image, though this use is\n"); fprintf(out, " discouraged.\n"); fprintf(out, " DESCRIPTION is optional; the default is an empty string\n"); fprintf(out, " The next part specfies the resolution and color information. If\n"); fprintf(out, " the MIME-TYPE is image/jpeg, image/png, or image/gif, you can\n"); fprintf(out, " usually leave this empty and they can be detected from the file.\n"); fprintf(out, " Otherwise, you must specify the width in pixels, height in pixels,\n"); fprintf(out, " and color depth in bits-per-pixel. If the image has indexed colors\n"); fprintf(out, " you should also specify the number of colors used.\n"); fprintf(out, " FILE is the path to the picture file to be imported, or the URL if\n"); fprintf(out, " MIME type is -->\n"); fprintf(out, "--export-picture-to=FILE Export PICTURE block to a file. Use '-' for stdout.\n"); fprintf(out, " Only one FLAC file may be specified. The first PICTURE\n"); fprintf(out, " block will be exported unless --export-picture-to is\n"); fprintf(out, " preceded by a --block-number=# option to specify the exact\n"); fprintf(out, " metadata block to extract. Note that the block number is\n"); fprintf(out, " the one shown by --list.\n"); fprintf(out, "--add-replay-gain Calculates the title and album gains/peaks of the given\n"); fprintf(out, " FLAC files as if all the files were part of one album,\n"); fprintf(out, " then stores them in the VORBIS_COMMENT block. The tags\n"); fprintf(out, " are the same as those used by vorbisgain. Existing\n"); fprintf(out, " ReplayGain tags will be replaced. If only one FLAC file\n"); fprintf(out, " is given, the album and title gains will be the same.\n"); fprintf(out, " Since this operation requires two passes, it is always\n"); fprintf(out, " executed last, after all other operations have been\n"); fprintf(out, " completed and written to disk. All FLAC files specified\n"); fprintf(out, " must have the same resolution, sample rate, and number\n"); fprintf(out, " of channels. The sample rate must be one of 8, 11.025,\n"); fprintf(out, " 12, 16, 22.05, 24, 32, 44.1, or 48 kHz.\n"); fprintf(out, "--scan-replay-gain Like --add-replay-gain, but only analyzes the files\n"); fprintf(out, " rather than writing them to tags.\n"); fprintf(out, "--remove-replay-gain Removes the ReplayGain tags.\n"); fprintf(out, "--add-seekpoint={#|X|#x|#s} Add seek points to a SEEKTABLE block\n"); fprintf(out, " # : a specific sample number for a seek point\n"); fprintf(out, " X : a placeholder point (always goes at the end of the SEEKTABLE)\n"); fprintf(out, " #x : # evenly spaced seekpoints, the first being at sample 0\n"); fprintf(out, " #s : a seekpoint every # seconds; # does not have to be a whole number\n"); fprintf(out, " If no SEEKTABLE block exists, one will be created. If\n"); fprintf(out, " one already exists, points will be added to the existing\n"); fprintf(out, " table, and any duplicates will be turned into placeholder\n"); fprintf(out, " points. You may use many --add-seekpoint options; the\n"); fprintf(out, " resulting SEEKTABLE will be the unique-ified union of\n"); fprintf(out, " all such values. Example: --add-seekpoint=100x\n"); fprintf(out, " --add-seekpoint=3.5s will add 100 evenly spaced\n"); fprintf(out, " seekpoints and a seekpoint every 3.5 seconds.\n"); fprintf(out, "--add-padding=length Add a padding block of the given length (in bytes).\n"); fprintf(out, " The overall length of the new block will be 4 + length;\n"); fprintf(out, " the extra 4 bytes is for the metadata block header.\n"); fprintf(out, "\n"); fprintf(out, "Major operations:\n"); fprintf(out, "--version\n"); fprintf(out, " Show the metaflac version number.\n"); fprintf(out, "--list\n"); fprintf(out, " List the contents of one or more metadata blocks to stdout. By default,\n"); fprintf(out, " all metadata blocks are listed in text format. Use the following options\n"); fprintf(out, " to change this behavior:\n"); fprintf(out, "\n"); fprintf(out, " --block-number=#[,#[...]]\n"); fprintf(out, " An optional comma-separated list of block numbers to display. The first\n"); fprintf(out, " block, the STREAMINFO block, is block 0.\n"); fprintf(out, "\n"); fprintf(out, " --block-type=type[,type[...]]\n"); fprintf(out, " --except-block-type=type[,type[...]]\n"); fprintf(out, " An optional comma-separated list of block types to be included or ignored\n"); fprintf(out, " with this option. Use only one of --block-type or --except-block-type.\n"); fprintf(out, " The valid block types are: STREAMINFO, PADDING, APPLICATION, SEEKTABLE,\n"); fprintf(out, " VORBIS_COMMENT. You may narrow down the types of APPLICATION blocks\n"); fprintf(out, " displayed as follows:\n"); fprintf(out, " APPLICATION:abcd The APPLICATION block(s) whose textual repre-\n"); fprintf(out, " sentation of the 4-byte ID is \"abcd\"\n"); fprintf(out, " APPLICATION:0xXXXXXXXX The APPLICATION block(s) whose hexadecimal big-\n"); fprintf(out, " endian representation of the 4-byte ID is\n"); fprintf(out, " \"0xXXXXXXXX\". For the example \"abcd\" above the\n"); fprintf(out, " hexadecimal equivalalent is 0x61626364\n"); fprintf(out, "\n"); fprintf(out, " NOTE: if both --block-number and --[except-]block-type are specified,\n"); fprintf(out, " the result is the logical AND of both arguments.\n"); fprintf(out, "\n"); #if 0 /*@@@ not implemented yet */ fprintf(out, " --data-format=binary|text\n"); fprintf(out, " By default a human-readable text representation of the data is displayed.\n"); fprintf(out, " You may specify --data-format=binary to dump the raw binary form of each\n"); fprintf(out, " metadata block. The output can be read in using a subsequent call to\n"); fprintf(out, " "metaflac --append --from-file=..."\n"); fprintf(out, "\n"); #endif fprintf(out, " --application-data-format=hexdump|text\n"); fprintf(out, " If the application block you are displaying contains binary data but your\n"); fprintf(out, " --data-format=text, you can display a hex dump of the application data\n"); fprintf(out, " contents instead using --application-data-format=hexdump\n"); fprintf(out, "\n"); #if 0 /*@@@ not implemented yet */ fprintf(out, "--append\n"); fprintf(out, " Insert a metadata block from a file. The input file must be in the same\n"); fprintf(out, " format as generated with --list.\n"); fprintf(out, "\n"); fprintf(out, " --block-number=#\n"); fprintf(out, " Specify the insertion point (defaults to last block). The new block will\n"); fprintf(out, " be added after the given block number. This prevents the illegal insertion\n"); fprintf(out, " of a block before the first STREAMINFO block. You may not --append another\n"); fprintf(out, " STREAMINFO block.\n"); fprintf(out, "\n"); fprintf(out, " --from-file=filename\n"); fprintf(out, " Mandatory 'option' to specify the input file containing the block contents.\n"); fprintf(out, "\n"); fprintf(out, " --data-format=binary|text\n"); fprintf(out, " By default the block contents are assumed to be in binary format. You can\n"); fprintf(out, " override this by specifying --data-format=text\n"); fprintf(out, "\n"); #endif fprintf(out, "--remove\n"); fprintf(out, " Remove one or more metadata blocks from the metadata. Unless\n"); fprintf(out, " --dont-use-padding is specified, the blocks will be replaced with padding.\n"); fprintf(out, " You may not remove the STREAMINFO block.\n"); fprintf(out, "\n"); fprintf(out, " --block-number=#[,#[...]]\n"); fprintf(out, " --block-type=type[,type[...]]\n"); fprintf(out, " --except-block-type=type[,type[...]]\n"); fprintf(out, " See --list above for usage.\n"); fprintf(out, "\n"); fprintf(out, " NOTE: if both --block-number and --[except-]block-type are specified,\n"); fprintf(out, " the result is the logical AND of both arguments.\n"); fprintf(out, "\n"); fprintf(out, "--remove-all\n"); fprintf(out, " Remove all metadata blocks (except the STREAMINFO block) from the\n"); fprintf(out, " metadata. Unless --dont-use-padding is specified, the blocks will be\n"); fprintf(out, " replaced with padding.\n"); fprintf(out, "\n"); fprintf(out, "--merge-padding\n"); fprintf(out, " Merge adjacent PADDING blocks into single blocks.\n"); fprintf(out, "\n"); fprintf(out, "--sort-padding\n"); fprintf(out, " Move all PADDING blocks to the end of the metadata and merge them into a\n"); fprintf(out, " single block.\n"); return message? 1 : 0; }
int main(int argc, char* argv[]) { po::options_description options("Options"); // Don't use default values because the help print it ugly and too wide options.add_options() ("move,m", "move files rather than copy") ("symlink,s", "symlink files rather than copy (posix only)") ("order,o", po::value<std::string>(), "order and types of metadata to read\ne=exif, i=iptc, f=file (default: eif)") ("unsorted,u", po::value<std::string>(), "special directory to store unsorted files (default: unsorted)") ("dups,d", po::value<std::string>(), "special directory to store files with duplicate names (default: duplicates)") ("force,f", "overwrite duplicate files instead of using special directory") ("rename,r", "rename duplicate files instead of using special directory") ("ignore,i", "ignore both unsorted and duplicate files instead of using special directories") ("ignore-unsorted", "ignore unsorted files instead of using special directory") ("ignore-dups", "ignore duplicate files instead of using special directory") ("verify", "verify copied or moved files and exit if incorrect") ("exclude,x", po::value< std::vector<std::string> >(), "exclude directories and files that contain arg (case sensitive on all platforms)") ("limit-depth,l", po::value<long>(), "limit recursion to specified depth (0 disables recursion)") ("verbose,v", "prints operations as they happen") ("dry-run,n", "do not make actual changes (implies verbose)") ("help,h", "show this help message then exit") ("version,V", "show program version then exit") ; po::options_description hidden("Hidden Options"); hidden.add_options() ("source-dir", po::value< std::string >(), "directory of files to organize, may end in file wildcard") ("dest-dir", po::value< std::string >(), "desination directory for files, may not be within source-dir") ("pattern", po::value< std::string >(), "subdirectory pattern for grouping files within dest-dir") ; po::options_description cmdline; cmdline.add(options).add(hidden); po::positional_options_description positional; positional.add("source-dir", 1); positional.add("dest-dir", 1); positional.add("pattern", 1); try { po::variables_map vm; po::store(po::command_line_parser(argc, argv). options(cmdline).positional(positional).run(), vm); po::notify(vm); if (vm.count("help")) { usage_full(options, argv[0]); return 0; } if (vm.count("version")) { version(); return 0; } conflicting(vm, "verify", "symlink"); conflicting(vm, "move", "symlink"); conflicting(vm, "unsorted", "ignore"); conflicting(vm, "unsorted", "ignore-unsorted"); conflicting(vm, "dups", "ignore"); conflicting(vm, "dups", "ignore-dups"); conflicting(vm, "force", "ignore"); conflicting(vm, "force", "ignore-dups"); conflicting(vm, "force", "rename"); conflicting(vm, "rename", "ignore"); conflicting(vm, "rename", "ignore-dups"); required(vm, "source-dir"); required(vm, "dest-dir"); required(vm, "pattern"); const bool dry_run = vm.count("dry-run") != 0; g_verbose = (vm.count("verbose") != 0 || dry_run); std::string order = "eif"; if(vm.count("order")) { order = vm["order"].as<std::string>(); boost::to_lower(order); if(order.length() > 3) { throw std::logic_error(std::string("order is longer than 4 characters")); } } unsigned i = 0; std::string::iterator end = order.end(); for(std::string::iterator iter = order.begin(); iter != end && i < 4; ++iter, ++i) { switch(*iter) { case 'e': g_run_order[i] = EXIF_SLOT; break; case 'i': g_run_order[i] = IPTC_SLOT; break; case 'x': throw std::logic_error(std::string("xmp not implemented yet '") + *iter + "'"); break; case 'f': g_run_order[i] = FILE_SLOT; break; default: throw std::logic_error(std::string("unknown order character '") + *iter + "'"); } } const fs::path source_dir( vm["source-dir"].as<std::string>() ); if( !exists(source_dir) || !is_directory(source_dir) ) { throw std::logic_error(std::string("source '") + source_dir.string() + "' must exist and be a directory"); } const fs::path dest_dir( vm["dest-dir"].as<std::string>() ); if( exists(dest_dir) && !is_directory(dest_dir) ) { throw std::logic_error(std::string("destination '") + dest_dir.string() + "' must be a directory"); } // Boost doesn't seem to have a way to get a canonical path, so this // simple test is easy to confuse with some ../../'s in the paths. Oh // well, this is good enough for now. fs::path test_dest(dest_dir); for(; !test_dest.empty(); test_dest = test_dest.parent_path()) { if(fs::equivalent(source_dir, test_dest)) { throw std::logic_error(std::string("dest-dir must not be within source-dir")); } } // Disect the pattern std::string pattern = vm["pattern"].as<std::string>(); boost::regex regex( "([^@]*)(@[[:alpha:]]+)([^@]*)"); boost::sregex_iterator m_iter = make_regex_iterator(pattern, regex); boost::sregex_iterator m_end; for( ; m_iter != m_end; ++m_iter) { const boost::smatch &match = *m_iter; const std::string &pre = match[1]; const std::string &pat = match[2]; const std::string &post = match[3]; // Should put this in a map, but there aren't that many options now bool found = false; for( const Pattern *pattern = g_patterns; pattern->pat.length(); ++pattern) { if(pattern->pat == pat) { PathPart part(pre, pattern, post); g_path_parts.push_back(part); found = true; break; } } if(!found) { throw std::logic_error(std::string("unknown pattern '") + pat + "'"); } } // Assign defaults to params that need them const bool ignore = vm.count("ignore") != 0; std::vector<std::string> excludes; if(vm.count("exclude")) excludes = vm["exclude"].as< std::vector<std::string> >(); long limit_depth = LONG_MAX; if(vm.count("limit-depth")) { limit_depth = vm["limit-depth"].as<long>(); // Boost program_options doesn't work with unsigned, so do it manually if( limit_depth < 0 ) throw std::logic_error(std::string("recursion depth limit must be positive")); } std::string dups = "duplicates"; if(vm.count("dups")) dups = vm["dups"].as<std::string>(); const fs::path dups_dir = dest_dir / dups; std::string unsorted = "unsorted"; if(vm.count("unsorted")) unsorted = vm["unsorted"].as<std::string>(); const fs::path unsorted_dir = dest_dir / unsorted; ProcessParams params = { dest_dir, dry_run, (vm.count("ignore-dups") != 0 || ignore), (vm.count("ignore-unsorted") != 0 || ignore), vm.count("force") != 0, vm.count("rename") != 0, vm.count("symlink") != 0, vm.count("verify") != 0, vm.count("move") != 0, limit_depth, dups_dir, unsorted_dir, excludes, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; process_directory(source_dir, 0, params); std::string op = "copied"; if(params.symlink) op = "linked"; else if(params.move) op = "moved"; if(dry_run) op = std::string("would be ") + op; if(g_neednewline) std::cout << "\n"; std::cout << "\n" << params.ok_count << " files " << op << "\n"; std::cout << " " << params.dups_count << " duplicates\n"; std::cout << " " << params.unsorted_count << " unsorted\n"; if(params.dups_ignored_count) std::cout << params.dups_ignored_count << " duplicates ignored\n"; if(params.unsorted_ignored_count) std::cout << params.unsorted_ignored_count << " unsorted ignored\n"; if(params.dir_ex_count) std::cout << params.dir_ex_count << " directories excluded\n"; if(params.file_ex_count) std::cout << params.file_ex_count << " files excluded\n"; if(params.dir_err_count) std::cout << params.dir_err_count << " directory errors\n"; if(params.file_err_count) std::cout << params.file_err_count << " file errors\n"; return 0; } catch (Exiv2::AnyError& e) { error(e, std::string("Aborting")); return -1; } catch(std::logic_error& e) { error(e, ""); usage_header(argv[0]); std::cout << argv[0] << " -h for more help" << std::endl; return -2; } catch(std::exception& e) { error(e, "Aborting"); return -3; } }