4

I'm trying to copy all .h files in a directory and all subdirectories into another folder using the copy command:

cp --parents -r tensorflow/lite/**/*.h libtensorflowlite-2.13.0-linux/include

The above glob only copies .h files in tensorflow/lite/XXX/*.h and doesn't include .h files further down (eg. tensorflow/lite/XXX/XXX.h) or in the root (tensorflow/lite/*.h). To workaround this, I have to issue several cp commands for all expected levels of recursion:

cp --parents -r tensorflow/lite/*.h libtensorflowlite-2.13.0-linux/include
cp --parents -r tensorflow/lite/**/*.h libtensorflowlite-2.13.0-linux/include
cp --parents -r tensorflow/lite/**/**/*.h libtensorflowlite-2.13.0-linux/include
cp --parents -r tensorflow/lite/**/**/**/*.h libtensorflowlite-2.13.0-linux/include

I know I'm missing something obvious here. Is there an easier way to create a glob that says "all files ending in .h in all subdirectories recursively"?

Brad
  • 155

2 Answers2

20

**/ to match any level of subdirectories is from the zsh shell from 1992.

ksh93 did copy it in 2003, but made it disabled by default for backward compatibility (where before ** was the same as *), enabled with set -G/set -o globstar. bash was one of the last shells to add that feature in 2009 but did it à la ksh93 (though bogus until 5.0), enabled with shopt -s globstar.

So:

cp --parents tensorflow/lite/**/*.h libtensorflowlite-2.13.0-linux/include

Would work in zsh (or to some extent fish where ** is enabled by default though works slightly differently from zsh), but you'd need to enable the globstar or equivalent option in other shells first:

set   -o globstar      # ksh93
set   -o extended-glob # yash
set      globstar      # tcsh
shopt -s globstar      # bash

For more details, see: The result of ls * , ls ** and ls ***

6

This command will find all .h files in tensorflow/lite and its subdirectories and copy them with their relative paths to the destination directory libtensorflowlite-2.13.0-linux/include.

find tensorflow/lite -type f -name "*.h" -exec cp --parents {} libtensorflowlite-2.13.0-linux/include/ \;

find tensorflow/lite

  • Starts the search from the tensorflow/lite directory.

-type f

  • Tells find to only look for files, not directories.

-name "*.h"

  • Specifies that only files with the .h extension should be considered.

-exec cp --parents {} libtensorflowlite-2.13.0-linux/include \;

  • -exec runs cp on each found file.

{} will be replaced with the path of each found .h file, and --parents ensures that the file's parent directories are created in the destination directory libtensorflowlite-2.13.0-linux/include if they don't exist.

Z0OM
  • 3,149