Home > Back-end >  ls doesn't produce the same output from Linux to MacOs
ls doesn't produce the same output from Linux to MacOs

Time:11-05

I am rewriting my own implementation of ls and I have found out that it doesn't work the same on my Macbook and my Xubuntu virtual machine.

The behavior I am testing is the use of a flag after the name of a directory, for example (Desktop and ft_ls are both directories):

/bin/ls -a Desktop -r ft_ls

produces this output on my Mac

ls: -r: No such file or directory
Desktop:
.       ..      .DS_Store   .localized

ft_ls:
.       ..      .git        Makefile    ft_ls       ft_ls.a     includes    libft       main.c      srcs        test

As you can see -r is considered as a file or a directory, however on my virtual machine with approximatively the same command -r is considered as an option (Bureau and ft_ls are both directories):

/bin/ls -a Bureau -r ft_ls

produces this output on Xubuntu

ft_ls:
srcs  Makefile    main.c    libft  .git  .dist  ..    .

Bureau/:
terminator.desktop  libft  ..  .

You can reproduce this behavior on your own system with:

/bin/ls -a "Any directory" -r "Any directory"

Am I doing something wrong or ls is different between Linux and Macos ? Thank you for your answers !

CodePudding user response:

The GNU C library version of getopt() thinks that you should be allowed to interleave options and arguments and therefore interprets the -r as an option, permuting the argument array to move the -r before the actual file arguments.

The POSIX specification for getopt() does not specify this behaviour, and many non-GNU implementations of getopt() do not permute the argument list. Macs (and presumably BSD systems) do not automatically use GNU getopt() — AFAIK, you'd have to install it and link with that library before linking with the system library.

On GNU systems, you can set the environment variable POSIXLY_CORRECT to suppress the permutation of options — I normally run with this set on my work machines and have to have cover scripts for a couple of work-provided scripts that rely on POSIXLY_CORRECT not being set — the cover scripts unset the variable and then run the official script.

Note that using -- as an option means that anything following it is not an option; the arguments after the -- option will be treated as non-option arguments by getopt().

For portable work, ensure that you put options before other arguments. And if you're running multiple commands that run other commands, use -- liberally.

One command sequence I use routinely is a variation on:

repeat -n 25 -i 300 -d 120 -c -- timecmd -m -- cvl

The repeat command repeats the command after the first double-dash (--) 25 times, with an initial delay of 300 seconds, thereafter a delay of 120 seconds, and prints out the repeat count in the identifying information. The timecmd -m times how long the command after the second -- takes, reporting in milliseconds. The cvl command looks at the current build log, reporting on the progress of the build and analyzing the log file for errors. It's crucial that the -m option is not interpreted by repeat (because it isn't a valid option to repeat). The -- ensures that the -m is given to timecmd and not subsumed by repeat. Timing the cvl command tells me if there are delays caused by network or other problems.

  • Related