为什么 bash 路径中 / 和 ////// 没有区别

为什么 bash 路径中 / 和 ////// 没有区别
ls -R /home/username/some/path

是相同的

ls - R /home///username/////////////some////path

/对bash 中' ' 字符的这种解释有什么解释吗?

我看不到 ls 程序的实现,但我可以看到我的实现:

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>


/* This program recursively prints files from given path. Should 
be equivalent to ls -R /given/path call from shell, except we 
don't concatenate '@' character at the end of symbolic link name, 
'/' if directory entry is directory, we don't sort output etc.. */

static void error_fatal (char *message);

static void traverse (char *filename);

int
main (int argc, char **argv)
{

assert (argc == 2);

traverse (argv[1]);

exit (EXIT_SUCCESS);
}

static void
traverse (char *filename)
{
struct stat stats;
DIR *dir;
struct dirent *entry;


  if (lstat (filename, &stats) < 0)
    error_fatal ("lstat");

  if (S_ISDIR (stats.st_mode))
{
    printf ("\n%s:\n", filename);

    if ((dir = opendir (filename)) == NULL)
      error_fatal ("opendir");

    if (chdir (filename) < 0)
      error_fatal ("chdir");

// In the first pass, we print all directory entries.

  while ((entry = readdir (dir)) != NULL)
    {
    if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, 
     ".."))
      continue;
    printf ("%s\t", entry->d_name);
}
  putchar ('\n');

  rewinddir (dir);

  // In the second pass, we examine if entry is directory, and if so, recursively call traverse() function.

  while ((entry = readdir (dir)) != NULL)
{
  if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
    continue;

  if (lstat (entry->d_name, &stats) < 0)
    error_fatal ("lstat");

  if (S_ISDIR (stats.st_mode))
    {

      char *a;
      int size =
    sizeof (char) * (2 + strlen (filename) +
             strlen (entry->d_name));
      a = (char *) malloc (size);
      if (a == NULL)
    error_fatal ("malloc");
      if (getcwd (a, size) == NULL)
    error_fatal ("getcwd");
      strcat (a, "/");
      strcat (a, entry->d_name);
      traverse (a);
      free (a);
    }

}


  if (chdir ("..") < 0)
error_fatal ("chdir");

  closedir (dir);

}
}

static void
error_fatal (char *message)
{
  perror (message);
  exit (EXIT_FAILURE);
}

uname -a给我:

Linux mk-Inspiron-5570 4.15.0-43-generic #46-Ubuntu SMP Thu Dec 6 14:45:28 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

bash --version给我:

GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

答案1

原因很简单:因为它是一个不bash具体的标准,而是由POSIX 标准, 看定义章节,第 3.266 节 路径名

多个连续的斜线被视为与一个斜线相同。

这些规范旨在实现可移植性,并指定类 Unix 操作系统和实用程序的行为方式。bash如果要将其用作/bin/shshell,则必须支持它,在 Ubuntu 上,它实际上曾经被符号链接到/bin/sh。另请参阅sh 链接到 dash 有什么意义?

答案2

来自开放群组基础规范第 7 期,2018 年版-> 定义 ->3.271 路径名

用于标识文件的字符串。在 POSIX.1-2017 的上下文中,路径名可能限制为 {PATH_MAX} 个字节,包括终止空字节。它具有可选的开头 <slash> 字符,后跟零个或多个由 <slash> 字符分隔的文件名。路径名可以可选地包含一个或多个尾随 <slash> 字符。多个连续的 <slash> 字符被视为与一个 <slash> 相同,除非恰好有两个前导 <slash> 字符的情况。

注意:如果路径名仅由与可移植文件名字符集(请参阅可移植文件名字符集)中的字符对应的字节、<slash> 字符和一个终止 <NUL> 字符组成,则该路径名在所有受支持的语言环境中均可用作字符串;否则,路径名可能只是一个字符串(而不是字符串)。此外,由于 <slash> 字符的单字节编码必须在所有语言环境中相同,并且不能出现在多字节字符中,因此即使路径名不是字符串,对路径名中 <slash> 字符的引用也是明确定义的。但是,此属性不一定适用于可移植文件名字符集中的其余字符。

路径名解析在路径名解析中有详细定义。

相关内容