在 Linux操作系统上,basename 命令从文件名中去除目录信息和后缀。这在要从长文件路径中提取文件名是特别有用。
本页介绍了 basename 的命令的使用及basename命令代码实现。
basename命令用法
basename 命令有两种语法。 第一个涉及后缀
basename NAME [SUFFIX]
第二个允许您添加选项:
basename OPTION
这里要说一下,不能将选项与后缀结合使用。 暂时不要混淆。
使用带有文件路径的 basename 命令将给出文件名:
自己写的basename命令,用来试验一下,是否跟linux自带的命令是否输出一致:
看效果就知道,我们输出是一样的。
basename 命令实际上非常简单。 它并不真正识别文件路径。 它只是查找斜杠 (/) 并打印最后一个斜杠之后的内容。
来看看代码是如何实现的。
char *base_name (char const *name)
{
char const *base = last_component (name);
size_t length;
/* 如果没有最后一个组件,则名称是文件系统根目录或
空字符串。 */
if (! *base)
return strndup (name, base_len(name));
/* 将一系列尾部斜杠折叠成一个。 */
length = base_len (base);
if (ISSLASH (base[length]))
length++;
/* 在带有驱动器号的系统上,“a/b:c”必须返回“./b:c”而不是
而不是“b:c”以避免与驱动器号混淆。 在系统上
使用纯 POSIX 语义,这不是问题。 */
if (FILE_SYSTEM_PREFIX_LEN (base))
{
char *p = (char *)malloc (length + 3);
p[0] = '.';
p[1] = '/';
memcpy (p + 2, base, length);
p[length + 2] = '\0';
return p;
}
/* 最后,复制基本名称。 */
return strndup(base, length);
}
例如,如果我通过删除文件名来运行上面的示例,它将产生以下结果。
linux自带的basename命令运行,猜的没有错的话,运行也是跟我们写的一样。
删除带后缀的文件扩展名
bashname 命令的主要用途是从文件路径中提取文件名。 您还可以在提取文件名时删除文件扩展名。
只需提及您要从输出末尾删除的内容。 因此,假设您想从 test.txt 中删除 .txt。 只需在 basename 命令的末尾添加它:
我们自己写的basename命令输出结果:
linux自带的basename效果:
从输入的最终组件的末尾删除后缀。 如果没有真正弄清楚文件的扩展名。 如果您提供 html(不带点)而不是 .html,您将得到“文件名”(末尾带点)。
linux自带的basename效果:
此外,如果您提供的后缀不在组件的末尾,则输出将保持为没有后缀。
与多个路径一起使用
使用选项 -a,您可以同时使用多个路径。
basename命令简易代码实现
size_t base_len (char const *name)
{
size_t len;
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
continue;
if (len == 1&& ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
return 2;
if (prefix_len&& len == prefix_len && ISSLASH (name[prefix_len]))
return prefix_len + 1;
return len;
}
char *base_name (char const *name)
{
char const *base = last_component (name);
size_t length;
/* 如果没有最后一个组件,则名称是文件系统根目录或
空字符串。 */
if (! *base)
return strndup (name, base_len(name));
/* 将一系列尾部斜杠折叠成一个。 */
length = base_len (base);
if (ISSLASH (base[length]))
length++;
if (FILE_SYSTEM_PREFIX_LEN (base))
{
char *p = (char *)malloc (length + 3);
p[0] = '.';
p[1] = '/';
memcpy (p + 2, base, length);
p[length + 2] = '\0';
return p;
}
/* 最后,复制基本名称。 */
return strndup(base, length);
}
/*如果存在 NAME 末尾的 SUFFIX,则删除它,除非 NAME
完全由后缀组成。 */
static void remove_suffix (char *name, const char *suffix)
{
char *np;
const char *sp;
np = name + strlen (name);
sp = suffix + strlen (suffix);
while (np > name && sp > suffix)
if (*--np != *--sp)
return;
if (np > name)
*np = '\0';
}
static void perform_basename (const char *string, const char *suffix, bool use_nuls)
{
char *name = base_name (string);
strip_trailing_slashes (name);
if (suffix && IS_RELATIVE_FILE_NAME (name) && ! FILE_SYSTEM_PREFIX_LEN (name))
remove_suffix (name, suffix);
fputs (name, stdout);
putchar (use_nuls ? '\0' : '\n');
free (name);
}
int main(int argc, char **argv)
{
bool multiple_names = false;
//optind: argv的当前索引值
while (true)
{
int c = getopt(argc, argv, "+a");
if (c == -1)
break;
switch (c)
{
case 'a':
multiple_names = true;
break;
default:
break;
}
}
if (argc < optind + 1)
{
printf("missing operand\n");
return -1;
}
if (!multiple_names && optind + 2 < argc)
{
printf("extra operand --> %s\n",strdup(argv[optind + 2]));
return -1;
}
if (multiple_names)
{
for (; optind < argc; optind++)
perform_basename (argv[optind], NULL, false);
}
else
perform_basename(argv[optind],optind + 2 == argc ? argv[optind + 1] : NULL, false);
return 0;
}
basename代码实现了获取路径中的文件名或路径名,还可以对末尾字符进行删除。
欢迎关注微信公众号【程序猿编码】,欢迎添加本人微信号(17865354792),交个朋友,咱们一起学习进步!