When ls
is called, it outputs all the files/directories in the current directory, attempting to fit as many as possible on each line. Why is it that when passed to wc -l
, it outputs the number of files? How does it decide how many lines to output its results in?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
When ls
is executed it parses various options. It also detect if output is a tty or not by isatty().
ls.c:
case LS_LS: /* This is for the `ls' program. */ if (isatty (STDOUT_FILENO)) { format = many_per_line; /* See description of qmark_funny_chars, above. */ qmark_funny_chars = true; } else { format = one_per_line; qmark_funny_chars = false; } break;
…
/* disable -l */ if (format == long_format) format = (isatty (STDOUT_FILENO) ? many_per_line : one_per_line);
etc.
If you want you can compile a simple test:
isawhat.c
#include <stdio.h> #include <unistd.h> int main(void) { if (isatty(STDOUT_FILENO)) { fprintf(stdout, "Word by word my world.n"); } else { fprintf(stdout, "HELP! Stranger handling my words!!n"); } fprintf(stderr, "Bye bye.n"); return 0; }
Compile by:
gcc -o isawhat isawhat.c
Then e.g.:
$ ./isawhat | sed 's/word/world/'
Width is measured in columns. One column is one character. It starts out with 80, then check if the environment variable COLUMNS is set and holds a valid int that is not larger then SIZE_MAX (Which is arch dependant – your terminal will never be that wide (at least not yet)).
Try e.g. echo $COLUMNS
. It most probably reflect the number of columns you have available in the window. As window get resized – this get updated. It most probably also get reset by various commands.
One way to set it a bit harder is by stty
. E.g. stty columns 60
. Use stty -a
to view all (man stty). A fun piece of software.
If compiled in it also query for columns by ioctl(), Window size detect.. By passing the filenumber for stdout to ioctl
and passing the request TIOCGWINSZ the structure winsize
get filled with the number of columns.
This can also be demonstrated by a simple c-code:
Compile, run and resize window. Should update. Ctrl+C to quit.
#include <stdio.h> #include <unistd.h> #include <sys/ioctl.h> #include <signal.h> static int run; void sig_handler(int sig) { switch (sig) { case SIGINT: case SIGTERM: case SIGSTOP: run = 0; break; } } void sig_trap(int sig) { if ((signal(sig, sig_handler)) == SIG_IGN) signal(sig, SIG_IGN); } int main(void) { struct winsize ws; sig_trap(SIGINT); sig_trap(SIGTERM); sig_trap(SIGSTOP); run = 1; while (run) { if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) { fprintf(stdout, "r %s: %3d, %s: %dr", "Columns", ws.ws_col, "Rows", ws.ws_row ); fflush(stdout); } usleep(5000); } fprintf(stdout, "n"); return 0; }
Method 2
When output is directed into a file descriptor other than a terminal (thus pipe, or file, or the like), ls
behaves as if it was invoked as ls -1
.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0