0

Using the cd commands and ls give the tree of your UNIX machine to a depth of 2 subdirectories starting from the root "/". If the number of files or directories is greater than 20, specify only the number of files or subdirectories.

I tried this so far:

cd /../.. | ls -l | wc -l

But I don't really know if that gives me what I need. I know WC. will count files number but I did not get that. cd/../../ since it looks like I heading two levels down. Well it looks confusing.

steve
  • 21,892
SAM.Am
  • 111
  • Could you please post what you have tried? And please tell us if this is homework. – fd0 Oct 13 '19 at 19:06
  • I didn't quite understand that thing about more than 20 directories or files. Is that some total number of the 2nd directory level, or in any single directory on that level (recursively?)? Do you mean "output" when you write "specify"? Besides, wc -l never counts files. It only counts lines of text. If filenames contains newlines, these would be counted multiple times by wc -l. – Kusalananda Oct 13 '19 at 19:16
  • wc associated with ls -l through the piping will count number of files . the command should display number of files of. all sub-directories of level 2 with their number of files . – SAM.Am Oct 13 '19 at 19:21
  • wc -l does not count files. It counts lines. Try creating an empty directory, and then run touch $'one\nfile' inside it. ls -l | wc -l will give you 3 (2 for the file, and one for the header that it always outputs when using its long format output). – Kusalananda Oct 13 '19 at 19:24

1 Answers1

0

Your command is nonsensical. First of all, cd /../.. is the same as cd /, i.e. it will just change the current working directory to the top-most directory in the directory hierarchy. Secondly, cd does not produce any output, so piping it to anything is not going to do much good.

Thirdly, ls -l will produce a listing of entries (names) in the current directory. You are using wc -l to count the number of lines in the output of ls -l. This number likely be at least one more than the real number of directory entries in any directory since ls -l outputs a sort of header (BSD ls doesn't do this for empty directories, but GNU ls always does). ls -l will not list hidden filenames, and it will (when piped to wc -l) produce multiple lines for files that have newlines embedded in their filenames.

Don't use ls for anything other than for looking at directory listings (with your eyes), and only ever use wc -l to count lines. There are smarter and quicker ways to count files.

Related:


To list the number of directory entries (names) inside all 2nd level subdirectories using bash, use something like

shopt -s nullglob dotglob

for dirpath in /*/*/; do
    set -- "$dirpath"/*
    printf '%d\t%s\n' "$#" "$dirpath"
done

This loops over all 2nd level directories. For each directory, it expands the * globbing pattern in the directory and sets the positional parameters to the resulting names. After doing so, the special variable $# will contain the number of positional parameters (names in the directory). We then print the directory pathname together with that count.

The nullglob and dotglob shell options are first set so that we correctly count hidden names and so that we get the correct count (0) for empty directories.

Would you want to have a recursive count of each subdirectory at level 2:

shopt -s nullglob dotglob globstar

for dirpath in /*/*/; do
    set -- "$dirpath"/**/*
    printf '%d\t%s\n' "$#" "$dirpath"
done

The globstar shell option in bash enables the use of **, which is a pattern that matches "recursively" down into subdirectories.

Would you want to only list the ones with 20 or more entries in them (here using the second variation from above, which counts names recursively in each subdirectory):

shopt -s nullglob dotglob globstar

for dirpath in /*/*/; do
    set -- "$dirpath"/**/*
    if [[ $# -ge 20 ]]; then
        printf '%d\t%s\n' "$#" "$dirpath"
    fi
done
Kusalananda
  • 333,661