72

I use the following line to find all sub-directories of the PWD and run svnadmin verify on each directory (I already know that they're Subversion repositories)

find ./* -maxdepth 0 -exec svnadmin verify {} \;

This works well, other than the fact that the output looks like this:

* Verifying repository metadata ...
* Verifying metadata at revision 1 ...
* Verifying metadata at revision 2 ...
* Verifying metadata at revision 4 ...
* Verifying metadata at revision 5 ...
* Verifying metadata at revision 6 ...
* Verifying metadata at revision 9 ...
* Verifying metadata at revision 10 ...
* Verifying metadata at revision 12 ...
* Verifying metadata at revision 14 ...
* Verifying metadata at revision 15 ...
* Verifying metadata at revision 18 ...
* Verifying metadata at revision 20 ...
* Verifying metadata at revision 22 ...
* Verified revision 0.
* Verified revision 1.
* Verified revision 2.
* Verified revision 3.
* Verified revision 4.
* Verified revision 5.
* Verified revision 6.
* Verified revision 7.
* Verified revision 8.
* Verified revision 9.
* Verified revision 10.
* Verified revision 11.
* Verified revision 12.
* Verified revision 13.
* Verified revision 14.
* Verified revision 15.
* Verified revision 16.
* Verified revision 17.
* Verified revision 18.
* Verified revision 19.
* Verified revision 20.
* Verified revision 21.
* Verified revision 22.
* Verified revision 23.
* Verified revision 0.
* Verifying repository metadata ...
* Verifying metadata at revision 4 ...
* Verifying metadata at revision 5 ...
* Verifying metadata at revision 6 ...
* Verifying metadata at revision 7 ...
* Verifying metadata at revision 9 ...
* Verified revision 0.
* Verified revision 1.
* Verified revision 2.
* Verified revision 3.
* Verified revision 4.
* Verified revision 5.
* Verified revision 6.
* Verified revision 7.
* Verified revision 8.
* Verified revision 9.

I'd really like find to print the filename before executing the svnadmin verify command, to make logging easier.

I've tried to squeeze a little ls in there but bodged it up, how should I do this (preferably simply)?

1

9 Answers 9

78

simply add a -printf option before

find -printf '%p' -exec command \;
3
  • 6
    Lovely, I changed '%p' to '%p\n' so that the name precedes the verify output on it's own line.
    – Arronical
    Jul 22, 2015 at 12:06
  • 28
    @Arronical if that's the format you want, you could replace the (formatted) -printf '%p\n' with the simpler -print Jul 22, 2015 at 12:56
  • 15
    find -name <a_name> -print -exec command {} \;
    – toliveira
    Mar 15, 2017 at 10:53
15

If you don't want to recurse, there's no point in using find in this case. It is far simpler to do it in the shell directly:

for d in */; do echo "$d"; svnadmin verify "$d"; done

The for d in */ will find all directories (the */ ensures only directories and no files are found); the echo "$d" will print the directory's name; the svnadmin verify "$d" will check the directory.

This can be run either directly from the command line or from within a script with no change in format.

5
  • 2
    This does look like a better way to achieve my goal, but I had to give the answer to Fiximan just because my title and question reference find so much. Thanks for improving my knowledge though!
    – Arronical
    Jul 22, 2015 at 12:35
  • This requires using a glob. Globbing is definitely useful & powerful, but in my personal experience the syntax is more difficult to set up, and often ends up needing other things like dotglob and globstar in bash, which creates a longer, more complicated script. I tend to save globs for large complicated tasks, while find's syntax is easier to throw together on the fly by just stringing together a bunch of filters and commands into a one-liner. Jul 22, 2016 at 19:32
  • @user5359531 neither globstar nor dotglob (unless you know you have hidden files and actually want them) are needed here. This is obviously a matter of opinion but you are the first person I've ever come across who considers the rather obtuse format of find simpler. I always prefer globs over find since I not only find them far simpler but they are also safer when dealing with arbitrary filenames that are passed to other programs.
    – terdon
    Jul 22, 2016 at 19:49
  • there are certainly use-cases to use find over shell globing beyond directory recursion, like using predicates
    – CervEd
    Jan 30, 2023 at 13:25
  • 1
    @CervEd of course, I was only referring to the specific problem mentioned here. There are loads of cases where find would be the right tool, it's just that this specific one isn't one of them. I added an "in this case" to clarify that I wasn't making a general statement.
    – terdon
    Jan 30, 2023 at 13:33
10
find ./* -maxdepth 0 -type d -exec bash -c 'echo "{}"; svnadmin verify "{}"' \;

I have added -type d if it is only directories.

2
  • I'd quote {}, at least in svnadmin verify {}
    – kos
    Jul 22, 2015 at 11:57
  • Thanks for the speedy response. So in this command does the -exec spawn a child shell, in which the 2 commands are run, using ; as end of line?
    – Arronical
    Jul 22, 2015 at 12:00
6

Try this:

for f in * ; do echo  -n "${f}:"; svnadmin verify "${f}"; done

If you just want directories(Thanks to @kos note):

for f in */ ; do echo  -n "${f}:"; svnadmin verify "${f}"; done
3
  • Nice, but this will process also files: for f in */ will process only directories
    – kos
    Jul 22, 2015 at 12:03
  • Will this only work in a script? Or can I issue it on the command line?
    – Arronical
    Jul 22, 2015 at 12:07
  • 1
    @Arronical will work also as command line
    – Maythux
    Jul 22, 2015 at 14:06
3
  • Use . -maxdepth 1 instead of ./*, you need only the first level in the folder structure
  • Use -type d, you need only folders
  • Use ! -name ".", you don't need .
  • Use -exec to start a shell
  • Use sh -c to start commands inside the shell

Your command

find . -maxdepth 1 -type d ! -name "." -exec sh -c 'echo "{}"; svnadmin verify "{}"' \;

or shorter

  • Use -prune if the file is a directory, do not descend into it

Your command

find . -mindepth 1 -prune -exec sh -c 'echo "{}"; svnadmin verify "{}"' \; 
1
  • -prune looks interesting. I used ./* -maxdepth 0 to avoid returning . from the find command. It doesn't cause any critical error, but I prefer not to have that in my output.
    – Arronical
    Jul 22, 2015 at 13:13
1

find has option flags for printing, which are already mentioned in other answers. If we look at the problem form the perspective of executing multiple commands for the same currently processed file, find allows using multiple -exec statements. This means we could opt for using:

find ./* -maxdepth 0 -exec echo {} \; -exec svnadmin verify {} \; 

Again, note that this approach is applicable to not just printing with echo, printf, or other utilities, but also other commands.

1

This will print the name and contents of files-only recursively..

find . -type f -printf '\n\n%p:\n' -exec cat {} \;
1

Best use find with XARGS, as it has verbose option exactly for this:

xargs --verbose / -t
      Print the command line on the standard error output before executing it.

So in your example:

find ./* -maxdepth 0 -type d | xargs -n1 --verbose svnadmin verify

svnadmin verify ./REPO_DIR_A
* Verified revision ...
svnadmin verify ./REPO_DIR_B
* Verified revision ...
0

It may be useful to pipe the find output to read loop:

find . | while read d; do echo "=== ${d}: ==="; svnadmin verify ${d}; done

It allows you to execute more complicated, compound command sequence with filenames returned by find, like in this fancy ls example:

find . | while read f; do echo ${f} | figlet -k; done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .