Linux下basename使用及代码实现

在 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),交个朋友,咱们一起学习进步!

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值