1

I have a directory called 'dir', and there is a subdirectory in it called 'subdir'. Subdir has many files in it. I would like write to list of these files on a CSV file and save it to in 'dir' directory with a command line on linux. My code creates the csv file but saves it in subdir but not dir. Where do I do wrong? I am in dir directory;

dir$ ls subdir >names.csv
  • oh, that is typo thanks for noticing that, yes i have that > sign to save – kutlus Jan 17 '19 at 0:00
1

You should achieve it by using the for loop.

If my understanding is right, you want to get a list of files in the subdir. So do something like this:

$ cd dir
$ for files in subdir/*;do echo $files|cut -d '/' -f 2 >>filelist.csv;done

Now, you can see there is a file called "filelist.csv" has been created under your dir directory.

| improve this answer | |
  • Well, new problem, now i have 5 subdirs in a dir directory, so there are subdir1 subdir2..subdir5. How can i write file list from all subdirs to one csv file and save it to dir? – kutlus Jan 17 '19 at 0:49
  • @kutlus You need to state that in your question from the beginning so that what you need is clear rather than waiting until after an answer has been given. – Nasir Riley Jan 17 '19 at 0:55
  • @kutlus Yes, simply change "subdir/*" to "subdir*/*". – NeilWang Jan 18 '19 at 1:17
2

As an easier alternative you could cd to subdir and use

printf "%s\n" * >../list.csv

This will give you a newline separated and newline terminated list with no commas involved. You can see it as a degererated csv file with only one column.

If you want to include hidden files (files with names that begin with a dot), you can use * .* instead of the sole *. If you want to exclude the . and .. directory names, use * .[^.]* ..?* instead. In total:

printf "%s\n" *             >../list.csv   # For non-hidden files.
printf "%s\n" * .*          >../list.csv   # For all files.
printf "%s\n" * .[^.]* ..?* >../list.csv   # For all files but `.` and `..`.

But keep in mind that filenames in Linux may contain newlines by themselves. In fact, the only unique single byte separator for filenames is the null byte.


Update due to this comment:

Let us assume that you have any number of subdirs whose non-hidden contents you want to catalog in separate files in the common parent directory. (Collecting all names in one file is much shorter, see this elegant solution. And, to tell the truth, I have not read your comment carefully enough.) This can be achieved in that parent directory (dir in your case) by

find . -mindepth 1 -maxdepth 1 -type d -exec bash -c 'cd {}; printf "%s\n" * >../$(basename {}).csv' \;

This requires the programs find, bash, and basename.

Using it you should take extra care, that dir does not contain files whose names conflict with the automatically generated csv lists.

Here is how it works: find considers each file that lies exactly one directory level below the current directory (.)—that is what -mindepth 1 -maxdepth 1 does—: If it is a directory (-type d) it executes (-exec) the command between -exec and the trailing \; after substituting the empty braces ({}) by the name of that directory. If we denote this name by <SUBDIR>, this results in

bash -c 'cd <SUBDIR>; printf "%s\n" * >../$(basename <SUBDIR>).csv'

This starts bash in a subprocess, causing it to execute the argument of the -c option as a shell script, namely

cd <SUBDIR>;
printf "%s\n" * >../$(basename <SUBDIR>).csv

which is pretty much the same as above. Here, the expression

$(basename <SUBDIR>)

is expanded to the basename of <SUBDIR>. This is necessary because <SUBDIR> will iterate through ./subdir1, ./subdir2, etc in your case. The corresponding basenames are subdir1, subdir2, etc.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.