Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

To check a successfull migration I'm using find to count the number of files, directories, symbolic links and files with more than one hard link. As the directories to check contain a huge number of files, each find run takes several hours. Thus I search for a way to separately count number of files, directories, symbolic links and files with more than one hard link within a single find run.

Here's what I currently do

num_files=$(find $directory -type f | wc -l)
num_directories=$(find $directory -type d | wc -l)
num_symlinks=$(find $directory -type l | wc -l)
num_hardlinks=$(find $directory -type f -links +1 | wc -l)

How can I get those four counters within one find run?

share|improve this question
    
I'm not sure this is the best approach to comparing two directories. Are you sure this is what you should be asking? –  Daniel Beck Jul 24 '13 at 7:28
    
The best way to compare two directories is probably a dry run of rsync. But I need to proof that rsync copied all files, directories, symbolic links and hard links and I don't know a better way than doing it with find. –  Florian Feldhaus Jul 24 '13 at 7:33

3 Answers 3

up vote 1 down vote accepted

The following should do it. It requires GNU find; on OS X, install e.g. findutil using Homebrew.

find $directory -type d -printf d -o -type l -printf l -o -type f -links +1 -printf h -o -type f -printf f

This will print one character per encountered file system entry:

  • d if it's a file
  • l if it's a symbolic link
  • h if it's a file with hard links
  • f if it's a file (only if not h)

Output looks like this (actual excerpt on my system):

dfddfdfddfdfddfdfddfdfddfdfddfddfdfddfdffffffffddfdffdfffffffffddfdldfllfdlldffffdfllfdlllllldffffdffffldfllfddffdldfddddffffflllldllllldlffffldfllfdlldffffdfllfddffddfddddfffffldfddddfffffdfddddfffffdlllldffffldfffflflllldffflfdffflfdfllfddffffldffffdfffflldfffflllldffffdffffdfffflldfllfddffdldfddddfffffdllllddflfffflldfllfddffffdffffdffffldffffdffffdffffdffffllldffffldffffdffffldffffldffffdffffdffffllllllldffffldffffdfffflllllldfffflldffddldfllfdldfffflldfffflldffffdfffflldffffdffffdfllfdlldfffflllldfllfdlldffffdfllfdlllllldffffdffdldfllfdlldfffflldfffflldffffldffffldfffflldfllfdldffffldffffldffdldffdddffddffddffddldfllfdlldffffdffffdfffflldfffflldffffdffffllldffffdffffdfllfddffffldfffflllldffffldfffflllldffffdfllfddffdldddddfffdddddfffdddddfffdddddfffdldlfffflldlffffllldfffllldffffdlffffdlffffldfffflldffdldfllfdllldffffdffffdffffldfllfdlllldfffflldfllfdldfddffffffl

Redirect output to a file, and then it becomes simple string processing to count later.

share|improve this answer
    
It worked fine on Mac OS X for me, but unfortunately I have to run the command on SunOS 5.10 where find doesn't support printf. Any suggestions how to achieve the same without printf? –  Florian Feldhaus Jul 24 '13 at 7:50
    
@FlorianFeldhaus You're on an almost decade old Solaris? You should probably add that to your question. Other than to compile and install a better find... no idea. FWIW OS X find does not support -printf, you probably installed something better already. –  Daniel Beck Jul 24 '13 at 7:56
    
Yes, I currently have to use it. The tools on it are not that old, but Solaris find does not support printf. I will try to get a Linux server where I have a recent GNU find. –  Florian Feldhaus Jul 24 '13 at 8:02

find $directory -type d -exec echo dirs \; -o -type l -exec echo symlinks \; -o -type f -links +1 -exec echo hardlinks \; -o -type f -exec echo files \; | sort | uniq -c

Produces output like:

 326 dirs
2164 files
  40 hardlinks
 164 symlinks
share|improve this answer

Using the answer from Daniel Beck I developed the following solution which should work for most versions of find and also provides the counting magic:

output=$(find $directory -type d -exec printf d \; -o -type l -exec printf l \; -o -type f -links +1 -exec printf h \; -o -type f -exec printf f \;)
num_files=$(echo $output | grep -o "f" | wc -l)
num_directories=$(echo $output | grep -o "d" | wc -l)
num_symlinks=$(echo $output | grep -o "l" | wc -l)
num_hardlinks=$(echo $output | grep -o "h" | wc -l)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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