0

i'm trying to count all the .txt files in the folders, the problem is that the main folder has more than one folder and inside everyone of them there are txt files , so in total i want to count the number of txt files . till now i've tried to build such a solution,but of course it's wrong:

 #!/bin/bash
  counter=0
  for i in $(ls /Da) ; do
   for j in $(ls i) ; do
    $counter=$counter+1
 done
 done 
  echo $counter

the error i'm getting is :ls cannot access i ...

the problem is that i don't know how i'm supposed to build the inner for loop as it depends on the external for loop(schema) ?

reeena11
  • 95
  • 1
  • 11
  • 3
    This would be easier with `find`: `find /Da -name '*.txt' | wc -l` – melpomene Nov 10 '18 at 16:30
  • Possible duplicate of https://stackoverflow.com/questions/9397816/how-can-i-find-and-count-number-of-files-matching-a-given-string – apatniv Nov 10 '18 at 16:31
  • hi , the problem is that linking between first loop and second loop not working , i can't do FIND for every folder that has folders inside also ... that's why o'm using loop! – reeena11 Nov 10 '18 at 16:38
  • @reeena11 `find` will recurse into subdirectories if you put the name in quotes like @melpomene did – ahota Nov 10 '18 at 16:40
  • 1
    Many of the errors in your script are reliably diagnosed by http://shellcheck.net/ – tripleee Nov 10 '18 at 16:47

3 Answers3

2

This can work for you

find . -name "*.txt" | wc -l

In the first part find looks for the *.txt from this folder (.) and its subfolders. In the second part wc counts the returnes lines (-l) of find.

miimote
  • 373
  • 2
  • 12
  • If there are subdirectories deper than two levels, this does something different than the OP's attempt. You can fix that with `find -maxdepth` but then if you know the level of nesting, you can just loop over a wildcard. – tripleee Nov 12 '18 at 06:01
  • Also, this is still susceptible to giving the wrong result if file names contain newlines. – tripleee Nov 12 '18 at 06:01
  • I've tried up to six level depth and several branches with my proposed command and works fine. – miimote Nov 12 '18 at 07:44
  • Sure, it works with infinite levels, but it's still wrong if that's not what the OP is trying to do. The question is unclear and I don't think they will be clarifying it; just pointing out that there is a difference. – tripleee Nov 12 '18 at 07:55
1

You want to avoid parsing ls and you want to quote your variables.

There is no need for repeated loops, either.

printf 'x\n' /Da/* /Da/*/* | wc -l

depending also on whether you expect the entries in /Da to be all files (in which case /Da/* will suffice), all directories (in which case /Da/*/* alone is enough), or both. Additionally, if you don't want to count directories at all, maybe switch to find /Da -type f -printf 'x\n' or similar.

There is no need to print the file names at all; this avoids getting the wrong result if a file name should ever contain a line feed (touch $'/Da/ick\npoo' to see this in action.)

More generally, a correct nested loop looks like

for i in list of things; do
    for j in different items, perhaps involving "$i"; do
        things with "$j" and perhaps also "$i"
    done
done
tripleee
  • 175,061
  • 34
  • 275
  • 318
-1

i is a variable, so you need to reference it via $, i.e. the second loop should be

for j in $(ls "$i") ; do
tripleee
  • 175,061
  • 34
  • 275
  • 318
kt_
  • 74
  • 5