ls -R /home/username/some/path
is the same as
ls - R /home///username/////////////some////path
Is there explanation for such interpretation of '/
' character in bash?
I can't see implementation of ls program, but I can see my implementation of it:
#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
gives me:
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
gives me:
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.
The reason is simple: because it's a standard which isn't
bash
specific, but is specified by POSIX standard, see Definitions chapter, section 3.266 PathnameThese specifications are meant for portability and specify how Unix-like operating system and utilities should behave.
bash
has to support it if it wants to be used as/bin/sh
shell, which on Ubuntu it actually used to be symlinked to/bin/sh
. See also What is the point of sh being linked to dash?From the The Open Group Base Specifications Issue 7, 2018 edition -> Definitions -> 3.271 Pathname: