How to call clang-format over a cpp project folder?

100,283

Solution 1

What about:

clang-format -i -style=WebKit *.cpp *.h

in the project folder. The -i option makes it inplace (by default formatted output is written to stdout).

Solution 2

Unfortunately, there is no way to apply clang-format recursively. *.cpp will only match files in the current directory, not subdirectories. Even **/* doesn't work.

Luckily, there is a solution: grab all the file names with the find command and pipe them in. For example, if you want to format all .h and .cpp files in the directory foo/bar/ recursively, you can do

find foo/bar/ -iname *.h -o -iname *.cpp | xargs clang-format -i

See here for additional discussion.

Solution 3

First create a .clang-format file if it doesn't exist:

clang-format -style=WebKit -dump-config > .clang-format

Choose whichever predefined style you like, or edit the resulting .clang-format file.

clang-format configurator is helpful.

Then run:

find . -regex '.*\.\(cpp\|hpp\|cc\|cxx\)' -exec clang-format -style=file -i {} \;

Other file extensions than cpp, hpp, cc and cxx can be used in the regular expression, just make sure to separate them with \|.

Solution 4

I recently found a bash-script which does exactly what you need:

https://github.com/eklitzke/clang-format-all

This is a bash script that will run clang-format -i on your code.

Features:

  • Finds the right path to clang-format on Ubuntu/Debian, which encode the LLVM version in the clang-format filename
  • Fixes files recursively
  • Detects the most common file extensions used by C/C++ projects

On Windows, I used it successfully in Git Bash and WSL.

Solution 5

When you use Windows (CMD) but don't want to use the PowerShell cannon to shoot this fly, try this:

for /r %t in (*.cpp *.h) do clang-format -i -style=WebKit "%t"

Don't forget to duplicate the two %s if in a cmd script.

Share:
100,283

Related videos on Youtube

user3639557
Author by

user3639557

Updated on July 08, 2022

Comments

  • user3639557
    user3639557 almost 2 years

    Is there a way to call something like clang-format --style=Webkit for an entire cpp project folder, rather than running it separately for each file?

    I am using clang-format.py and vim to do this, but I assume there is a way to apply this once.

  • mBardos
    mBardos over 8 years
    or if you are using a config file and want to format multiple file types: clang-format-3.6 -i -style=file *.cpp *.h *.hpp
  • Antimony
    Antimony about 8 years
    Unfortunately, that won't recurse into subdirectories.
  • sbarzowski
    sbarzowski about 8 years
    Yes, *.cpp will be expanded by the shell. clang just needs a list of files. More advanced options (like recursive globbing) depend on the features of your shell. See unix.stackexchange.com/questions/49913/recursive-glob on how to use ** construct.
  • sbarzowski
    sbarzowski about 8 years
    Well, **/*.cpp seems to work in (reasonably modern) bash. You may need to shopt -s globstar before.
  • phoenix
    phoenix about 7 years
    If you are using CMake, this post shows you how you can use CMake's GLOB_RECURSE to find all .cpp files and pass them to clang-format.
  • Alexander
    Alexander over 6 years
    The combination of find and xargs should use find ... -print0 and xargs -0 ... to ensure that all types of filenames are handled correctly.
  • nyanpasu64
    nyanpasu64 almost 6 years
    This command fails if any .cpp or .h files exist in pwd. find foo/bar/ -iname '*.h' -o -iname '*.cpp' | xargs clang-format -i will fix the issue.
  • Aaron Franke
    Aaron Franke over 4 years
    For -style=file is there a way to specify a custom file path? I tried -style=~/.clang-format and it doesn't work.
  • Alexander
    Alexander over 4 years
    Not that I know of, apart from changing the current directory.
  • Aaron Franke
    Aaron Franke over 4 years
    The ghetto solution I came up with is to make a function which first runs cp ~/.clang-format . then the find command in your answer.
  • Aaron Franke
    Aaron Franke almost 4 years
    What about with clang-tidy?
  • sbarzowski
    sbarzowski almost 4 years
    @AaronFranke Using *.cpp to generate a list of files should work. The clang-tidy command allows passing multiple files. ` USAGE: clang-tidy [options] <source0> [... <sourceN>] ` In practice that may not be the best way, though. Clang-tidy performs a much deeper analysis, so it requires the compiler flags for each file etc. When I used clang-tidy, I usually had a "compilation database" – a JSON file with the commands for each file and some script which went over it. It was a couple years back, maybe there is a better way now.
  • Aaron Franke
    Aaron Franke almost 4 years
    What if my C++ files are in subfolders?
  • sbarzowski
    sbarzowski almost 4 years
    You can use **. See: unix.stackexchange.com/questions/49913/recursive-glob.
  • vlad_tepesch
    vlad_tepesch almost 4 years
    does not work for me - only get invalid argument errors. Even with double - on style
  • sbarzowski
    sbarzowski almost 4 years
    @vlad_tepesch What exactly doesn't work? What command are you running exactly and what is the full error message (you might want to use pastebin for that)?
  • Eric Backus
    Eric Backus over 3 years
    I don't think globstar is on by default in bash, so you'd need to set it.
  • Anton Breusov
    Anton Breusov about 3 years
    Interesting but it doesn't work for me on macOS. But this version (with -E flag and without escaping special symbols does): find -E . -regex '.*\.(cpp|hpp|cc|cxx)' -exec clang-format -style=file -i {} \;
  • Alexander
    Alexander about 3 years
    Thanks for the info, Anton Breusov. -E does not work here on Arch Linux, but -regextype egrep does. Does -regextype egrep work on macOS too?