1/* basename -- strip directory and suffix from file names 2 Copyright (C) 1990-1997, 1999-2010 Free Software Foundation, Inc. 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17/* Usage: basename name [suffix] 18 NAME is a file name; SUFFIX is a suffix to strip from it. 19 20 basename /usr/foo/lossage/functions.l 21 => functions.l 22 basename /usr/foo/lossage/functions.l .l 23 => functions 24 basename functions.lisp p 25 => functions.lis */ 26 27#include <config.h> 28#include <getopt.h> 29#include <stdio.h> 30#include <sys/types.h> 31 32#include "system.h" 33#include "long-options.h" 34#include "error.h" 35#include "quote.h" 36 37/* The official name of this program (e.g., no `g' prefix). */ 38#define PROGRAM_NAME "basename" 39 40#define AUTHORS proper_name ("David MacKenzie") 41 42void 43usage (int status) 44{ 45 if (status != EXIT_SUCCESS) 46 fprintf (stderr, _("Try `%s --help' for more information.\n"), 47 program_name); 48 else 49 { 50 printf (_("\ 51Usage: %s NAME [SUFFIX]\n\ 52 or: %s OPTION\n\ 53"), 54 program_name, program_name); 55 fputs (_("\ 56Print NAME with any leading directory components removed.\n\ 57If specified, also remove a trailing SUFFIX.\n\ 58\n\ 59"), stdout); 60 fputs (HELP_OPTION_DESCRIPTION, stdout); 61 fputs (VERSION_OPTION_DESCRIPTION, stdout); 62 printf (_("\ 63\n\ 64Examples:\n\ 65 %s /usr/bin/sort Output \"sort\".\n\ 66 %s include/stdio.h .h Output \"stdio\".\n\ 67"), 68 program_name, program_name); 69 emit_ancillary_info (); 70 } 71 exit (status); 72} 73 74/* Remove SUFFIX from the end of NAME if it is there, unless NAME 75 consists entirely of SUFFIX. */ 76 77static void 78remove_suffix (char *name, const char *suffix) 79{ 80 char *np; 81 const char *sp; 82 83 np = name + strlen (name); 84 sp = suffix + strlen (suffix); 85 86 while (np > name && sp > suffix) 87 if (*--np != *--sp) 88 return; 89 if (np > name) 90 *np = '\0'; 91} 92 93int 94main (int argc, char **argv) 95{ 96 char *name; 97 98 initialize_main (&argc, &argv); 99 set_program_name (argv[0]); 100 setlocale (LC_ALL, ""); 101 bindtextdomain (PACKAGE, LOCALEDIR); 102 textdomain (PACKAGE); 103 104 atexit (close_stdout); 105 106 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version, 107 usage, AUTHORS, (char const *) NULL); 108 if (getopt_long (argc, argv, "+", NULL, NULL) != -1) 109 usage (EXIT_FAILURE); 110 111 if (argc < optind + 1) 112 { 113 error (0, 0, _("missing operand")); 114 usage (EXIT_FAILURE); 115 } 116 117 if (optind + 2 < argc) 118 { 119 error (0, 0, _("extra operand %s"), quote (argv[optind + 2])); 120 usage (EXIT_FAILURE); 121 } 122 123 name = base_name (argv[optind]); 124 strip_trailing_slashes (name); 125 126 /* Per POSIX, `basename // /' must return `//' on platforms with 127 distinct //. On platforms with drive letters, this generalizes 128 to making `basename c: :' return `c:'. This rule is captured by 129 skipping suffix stripping if base_name returned an absolute path 130 or a drive letter (only possible if name is a file-system 131 root). */ 132 if (argc == optind + 2 && IS_RELATIVE_FILE_NAME (name) 133 && ! FILE_SYSTEM_PREFIX_LEN (name)) 134 remove_suffix (name, argv[optind + 1]); 135 136 puts (name); 137 free (name); 138 139 exit (EXIT_SUCCESS); 140} 141