2

Let's say I have some directories which contain files. For example, the directories

/home/me/files/files_10
/home/me/files/files_11
/home/me/files/files_12

each of which contains some files corresponding to the last digits. For example, the directory /home/me/files/files_10 contains files

/home/me/files/files_10/file_100.txt
/home/me/files/files_10/file_102.txt
/home/me/files/files_10/file_105.txt
/home/me/files/files_10/file_106.txt
etc

The file numbers do grow larger, but do not necessarily include each digit (as 101, 103, 104 are missing in this case).

I am seeking to count the number of files between two inputted values. Given the example above, if my first value was 100 and my second value was 105, I would like the output to be 3. If the first value was 103 and the second value was 106, I would like the output to be 2. Furthermore, let's say I give a first value of 112 and a second value of 125. I would like to go into the corresponding directories (ending with 11 and 12), and count the number of files between these two values.

This is a simplified version of what I'm working with, but is functionally equivalent. What scheme could accomplish this? Thanks!

  • won't we have more than 10 files in a directory? – msp9011 Sep 23 at 12:04
3

Try this,

 ls /home/test/files/*/file_{112..125}.txt 2> /dev/null | wc -l
  • Thanks! Quick follow-up question: if I wanted to save the outputted count to a variable, how would I do that? – theta Sep 23 at 13:26
  • 2
    @theta: somevariable="$( somecommand )" – markgraf Sep 23 at 13:39
2

You could of course use find but also less frequently used updatedb and locate.

First, we need to use updatedb to create a database of existing files that subsequent locate commands will use. Go to /home/me/files and do:

updatedb --require-visibility 0 -o locate.db -U .

Now we're ready to use locate in conjunction with Bash {a..b} syntax to search for a list of files. For example:

$ locate -d ./locate.db file_{112..125}.txt
./files_11/file_112.txt
./files_11/file_113.txt
./files_12/file_124.txt
./files_12/file_125.txt
$ locate -d ./locate.db file_{100..105}.txt
./files_10/file_100.txt
./files_10/file_102.txt
./files_10/file_105.txt
$ locate -d ./locate.db file_{103..106}.txt
./files_10/file_105.txt
./files_10/file_106.txt

To show only a number of found files pipe locate output through wc -l.

The advantage of this solution is that locate works very fast.

The disadvantage is that you will have re-create the database manually each time new files are added or renamed (or maybe use inotify) and that locate cannot replace found filenames with NUL which will cause wc -l to return incorrect count in case of files that have a new line in their names.

2

If you're only looking to count the numbered files from x to y included:

$ tree files/
files/
├── file_100.txt
├── file_102.txt
├── file_105.txt
└── file_106.txt

0 directories, 4 files


$ start=103; end=106; echo files/* \
  | grep -o '[[:digit:]]*' \
  | awk '{ if ($1 >='$start' && $1 <= '$end') {++count}} END { print count }'
2

But if you are really sure there are no spaces or linebreaks in your filenames, @msp9011's answer is way easier...

  • @Freddy : fixed, thanks! – markgraf Sep 23 at 13:16

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.