1 /* basename -- strip directory and suffix from file names
2 Copyright (C) 1990-2015 Free Software Foundation, Inc.
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.
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.
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/>. */
20 #include <sys/types.h>
26 /* The official name of this program (e.g., no 'g' prefix). */
27 #define PROGRAM_NAME "basename"
29 #define AUTHORS proper_name ("David MacKenzie")
31 static struct option
const longopts
[] =
33 {"multiple", no_argument
, NULL
, 'a'},
34 {"suffix", required_argument
, NULL
, 's'},
35 {"zero", no_argument
, NULL
, 'z'},
36 {GETOPT_HELP_OPTION_DECL
},
37 {GETOPT_VERSION_OPTION_DECL
},
44 if (status
!= EXIT_SUCCESS
)
49 Usage: %s NAME [SUFFIX]\n\
50 or: %s OPTION... NAME...\n\
52 program_name
, program_name
);
54 Print NAME with any leading directory components removed.\n\
55 If specified, also remove a trailing SUFFIX.\n\
58 emit_mandatory_arg_note ();
61 -a, --multiple support multiple arguments and treat each as a NAME\n\
62 -s, --suffix=SUFFIX remove a trailing SUFFIX; implies -a\n\
63 -z, --zero end each output line with NUL, not newline\n\
65 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
66 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
70 %s /usr/bin/sort -> \"sort\"\n\
71 %s include/stdio.h .h -> \"stdio\"\n\
72 %s -s .h include/stdio.h -> \"stdio\"\n\
73 %s -a any/str1 any/str2 -> \"str1\" followed by \"str2\"\n\
75 program_name
, program_name
, program_name
, program_name
);
76 emit_ancillary_info (PROGRAM_NAME
);
81 /* Remove SUFFIX from the end of NAME if it is there, unless NAME
82 consists entirely of SUFFIX. */
85 remove_suffix (char *name
, const char *suffix
)
90 np
= name
+ strlen (name
);
91 sp
= suffix
+ strlen (suffix
);
93 while (np
> name
&& sp
> suffix
)
100 /* Perform the basename operation on STRING. If SUFFIX is non-NULL, remove
101 the trailing SUFFIX. Finally, output the result string. */
104 perform_basename (const char *string
, const char *suffix
, bool use_nuls
)
106 char *name
= base_name (string
);
107 strip_trailing_slashes (name
);
109 /* Per POSIX, 'basename // /' must return '//' on platforms with
110 distinct //. On platforms with drive letters, this generalizes
111 to making 'basename c: :' return 'c:'. This rule is captured by
112 skipping suffix stripping if base_name returned an absolute path
113 or a drive letter (only possible if name is a file-system
115 if (suffix
&& IS_RELATIVE_FILE_NAME (name
) && ! FILE_SYSTEM_PREFIX_LEN (name
))
116 remove_suffix (name
, suffix
);
118 fputs (name
, stdout
);
119 putchar (use_nuls
? '\0' : '\n');
124 main (int argc
, char **argv
)
126 bool multiple_names
= false;
127 bool use_nuls
= false;
128 const char *suffix
= NULL
;
130 initialize_main (&argc
, &argv
);
131 set_program_name (argv
[0]);
132 setlocale (LC_ALL
, "");
133 bindtextdomain (PACKAGE
, LOCALEDIR
);
134 textdomain (PACKAGE
);
136 atexit (close_stdout
);
140 int c
= getopt_long (argc
, argv
, "+as:z", longopts
, NULL
);
149 /* Fall through: -s implies -a. */
152 multiple_names
= true;
159 case_GETOPT_HELP_CHAR
;
160 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
163 usage (EXIT_FAILURE
);
167 if (argc
< optind
+ 1)
169 error (0, 0, _("missing operand"));
170 usage (EXIT_FAILURE
);
173 if (!multiple_names
&& optind
+ 2 < argc
)
175 error (0, 0, _("extra operand %s"), quote (argv
[optind
+ 2]));
176 usage (EXIT_FAILURE
);
181 for (; optind
< argc
; optind
++)
182 perform_basename (argv
[optind
], suffix
, use_nuls
);
185 perform_basename (argv
[optind
],
186 optind
+ 2 == argc
? argv
[optind
+ 1] : NULL
, use_nuls
);