15

So I have a repo with some of my config files and I'm trying to create a makefile to install them in the homedir. The problem I have is that when I run the following command straight in bash

install -m 755 -d ~/path/to/dotfilesDir/ ~/

seemingly nothing happens while

install -m 755 ~/path/to/dotfilesDir/{file1,file2,...} ~/

works as intended.

Why doesn't the first (easier and cleaner) solution work?

7

From a look at the man page, it seems that install will not do what you want.

Indeed, the Synopsis section indicates a usage of the form:

install [OPTION]... -d DIRECTORY...

and later on, the man page says:

-d, --directory
treat all arguments as directory names; create all components of the specified directories

So it seems to me that the point of this option is to be able to install a complicated (but empty) directory structure à la mkdir -p ....

You can accomplish what you want with a loop:

for file in /path/to/DotFiles/dir/*;do
    install -m 755 "$file" ~/
done

Or, if there are many levels under /path/to/DotFiles/dir, you can use find:

find /path/to/DotFiles/dir/ -type f -exec 'install -m 755 "{}" ~/' +
  • Create all components of the specified directories = Create the subdirs but not the files? – nathdwek Nov 1 '14 at 23:22
  • @nathdwek Right. This way you can create a complex (skeleton) directory structure under, say, your home directory using install -m 755 -d ~/foo/bar/baz – Joseph R. Nov 1 '14 at 23:26
  • 1
    -exec 'install -m 755 "{}" ~/' + is not going to work, at least not on certain (all? most?) version of linux. May work on OSX or something. Using something like this is pretty straight forward if you want a oneliner: 1. create directories recursive: for d in $(find . -type d); do install -d --mode 755 "$d" "../install-test/$d"; done 2. create files recursive: for f in $(find . -type f); do install -D --mode 644 "$f" ../install-test/; done – Josh M. Jan 15 at 1:37
5

Starting from @Joseph R.'s answer, this is my solution to make it work with find, as I couldn't make his command work. (I don't think it does, because of the rules applying to \+: there can be nothing after the {} element.) (I couldn't comment. This whole paragraph can actually be removed.)

To copy all the files into the exact same directory (here target/directory):

find directory/to/copy -type f -exec install -Dm 755 "{}" "target/directory" \;

-D is not mandatory here, it will just create the non-existing directories to the target.

To copy a whole directory hierarchy and its files (this will omit empty directories) starting from where you currently are:

find directory/tree/to/copy -type f -exec install -Dm 755 "{}" "target/directory/{}" \;

As said, this will recreate the tree starting from $PWD. Also, if you need to copy the empty directory, on could find a way using the -type d of find and install -d.

So, in order to copy the tree, starting from a directory that is not $PWD:

(cd parent/directory && find directory/tree/to/copy -type f -exec install -Dm 755 "{}" "target/directory/{}" \;)

Notice how parent/directory isn't copied over.

Extra

For those using shell/fish, here's the line which does the same:

fish -c 'cd parent/directory; and find directory/tree/to/copy -type f -exec install -Dm 755 "{}" "target/directory/{}" \\;'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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