5

hi ı am triying to take the data of files in a folder with system function this is the code

char path[100],command[120];
    scanf("%s",&path);

sprintf(command,"echo $(ls %s) > something.txt",path);
            system(command);

but when I look to the something.txt there is no new line. This is the output, all on one line with many file names omitted:

acpi adjtime adobe apparmor.d arch-release asound.conf ati at-spi2 avahi bash.bash_logout ... wpa_supplicant X11 xdg xinetd.d xml yaourtrc

I did try -e -E -n options of echo but it didn't work. How to make a new line after each of these files?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Alper Fırat Kaya
  • 2,079
  • 1
  • 18
  • 18
  • have you tried **ls -l** – user1269942 Jun 15 '15 at 21:25
  • yeb same thing happens – Alper Fırat Kaya Jun 15 '15 at 21:26
  • There is one new line, which is to be expected. You need to execute: `echo "$(ls %s)"` to preserve the newlines in the `ls` output. See [Capturing multiple-line output to a Bash variable](http://stackoverflow.com/questions/613572/). Use: `snprintf(command, "echo \"$(ls %s)\" > something.txt", path);` and worry about the fact that you have more than 20 extra characters in the string so the 120 should be more like 130 if not 140. You should also use `scanf("%99s", path)` (no ampersand; add length limiting), and ideally check that it worked (`if (scanf(...) == 1) { ... OK ... }`). – Jonathan Leffler Jun 15 '15 at 21:26
  • Please don't use `system` for this sort of thing. Just use `printf` or `fputs` like a sane person. – o11c Jun 15 '15 at 21:32
  • 1
    @o11c: Running `ls` requires something analogous to `system`; it is being given a directory name and listing the contents. Granted, you could reengineer `ls` in C and use that, but it isn't achieving code reuse. – Jonathan Leffler Jun 15 '15 at 21:35
  • it didnt work with snprintf ı get the result "path"+ command not found and if ı make it sprintf same result – Alper Fırat Kaya Jun 15 '15 at 21:41
  • I miswrote the `snprintf()` calls, forgetting to add `sizeof(command)` as the second parameter -- my bad. – Jonathan Leffler Jun 15 '15 at 21:46
  • 1
    @JonathanLeffler `readdir` is really not that hard, and it means you don't have to invent a way to parse the output. – o11c Jun 15 '15 at 21:50

2 Answers2

6

You shouldn't use echo. Do just

sprintf(command,"ls %s > something.txt",path);
system(command);

When you use echo it outputs all command line arguments to the stdout, one by one, separated by the space character. Newline character (which is output of ls command) works as an argument separator, just as space.

Oleg Andriyanov
  • 5,069
  • 1
  • 22
  • 36
2

There is one new line, which is to be expected. The echo command prints all its arguments on a single line separated by spaces, which is the output you see.

You need to execute the result of:

echo "$(ls %s)"

to preserve the newlines in the ls output. See Capturing multiple-line output to a Bash variable.

Use:

snprintf(command, sizeof(command), "echo \"$(ls %s)\" > something.txt", path);`

Of course, the echo is redundant; it would be better simply to run:

ls %s

and hence:

snprintf(command, sizeof(command), "ls %s > something.txt", path);

If you keep the echo, you should worry about the fact that you have more than 20 extra characters in the format string so the 120 should be more like 130 if not 140.

You should also use scanf("%99s", path) (no ampersand; add length limiting), and ideally check that it worked (if (scanf(...) == 1) { ... OK ... }).

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Side issue: Using `snprintf()` certainly has advantages over `sprintf()`. Yet in this case, using `snprintf()` _without checking its return value_ and then calling `system(command)` ignores the remaining huge problem a mal-formed system command could invoke. – chux - Reinstate Monica Jun 15 '15 at 22:07