3

We use a numeric version control for files (ex: report01.log.01, report01.log.02, report01.log.03, etc.)

What I need to do is produce a list each file and the number of versions the file has.

Does Linux has a function to do this relatively easily?

closed as unclear what you're asking by Michael Homer, Anthon, countermode, Archemar, Anthony Geoghegan Apr 18 '17 at 9:09

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    See Recursive statistics on file types in directory - instead of extracting the part after the last dot you just have to extract the part before it. Other than that it's the same... – don_crissti Apr 17 '17 at 13:50
  • 3
    Please edit your question and give an example of the output you want to see. – terdon Apr 17 '17 at 14:22
  • Consider using a Perl or Python script for this. It will be more maintainable than the shell scripts various people have suggested. – zwol Apr 17 '17 at 23:41
5

Another approach : ls | cut -f1 -d. | uniq -c.

awk approach : ls | awk -F. '{a[$1]++}END{for(b in a){print b,a[b]}}'

(long winded) perl approach : ls|perl -e 'while(<>){$a{(split(/\./,$_))[0]}++}for(sort keys %a){print "$_ $a{$_}\n"}'

  • 1
    As I understand it, the OP wants to remove the last dot-delimited part, while you only keep the first one. – user2233709 Apr 17 '17 at 13:52
5

I'd advise against parsing the output of ls, find, etc (see ParsingLs - Greg's Wiki for an explanation of why that's a bad idea).

Instead, Parameter Expansion on a bash array can produce a list without the file extensions.

filelist=(*);                      # or filelist=(*.log.*) to be more precise
printf '%q\n' "${filelist[@]%.*}"  # or echo "${filelist[@]%.*}"

Then, to work on the files individually ..

for i in "${filelist[@]%.*}"; do
   echo "$i";
done

For OP's particular purpose, we can use a bash associative array to hold the count of versions.

filelist=(*.log.*)

declare -A count
for i in "${filelist[@]%.*}"; do 
  (( count["$i"]++ )); 
done

for j in "${!count[@]}"; do 
  printf '%q\t%q\n' "$j" "${count[$j]}";
done | sort

report01.log    6
report02.log    6
report03.log    6
report04.log    6
report05.log    6
2

Something like ls | sed -e 's/\.[0-9]\+$//' | sort | uniq -c should do what you want.

  • This is obviously a quick&dirty way to do this. – user2233709 Apr 17 '17 at 13:35
  • There's nothing wrong with quick&dirty. – Monty Harder Apr 17 '17 at 19:19
  • I think it’s up to the OP to decide if quick&dirty is good enough for him, but shalomb is right that it’s better not to parse the output of ls, so I’d rather recommend his solution than mine or steve’s. – user2233709 Apr 17 '17 at 20:43

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