I have a simple script that I understand most of, it's the find command that's unclear. I've got a lot of documentation but it's not serving to make it much clearer. My thought is that it is working like a for-loop, the currently found file is swapped in for {} and copied to $HOME/$dir_name, but how does the search with -path and -prune -o work? It's annoying to have such specific and relevant documentation and still not know what's going on.
#!/bin/bash
# The files will be search on from the user's home
# directory and can only be backed up to a directory
# within $HOME
read -p "Which file types do you want to backup " file_suffix
read -p "Which directory do you want to backup to " dir_name
# The next lines creates the directory if it does not exist
test -d $HOME/$dir_name || mkdir -m 700 $HOME/$dir_name
# The find command will copy files that match the
# search criteria ie .sh . The -path, -prune and -o
# options are to exclude the backdirectory from the
# backup.
find $HOME -path $HOME/$dir_name -prune -o \
-name "*$file_suffix" -exec cp {} $HOME/$dir_name/ \;
exit 0
This is just the documentation that I know I should be able to figure this out from.
-path pattern
File name matches shell pattern pattern. The metacharacters do not treat / or .
specially; so, for example,
find . -path "./sr*sc"
will print an entry for a directory called ./src/misc (if one exists). To ignore a
whole directory tree, use -prune rather than checking every file in the tree. For
example, to skip the directory src/emacs and all files and directories under it, and
print the names of the other files found, do something like this:
find . -path ./src/emacs -prune -o -print
From Findutils manual
— Action: -exec command ;
This insecure variant of the -execdir action is specified by
POSIX. The main difference is that the command is executed in the
directory from which find was invoked, meaning that {} is
expanded to a relative path starting with the name of one of the
starting directories, rather than just the basename of the matched
file.While some implementations of find replace the {} only where
it appears on its own in an argument, GNU find replaces {}
wherever it appears.
And
For example, to compare each C header file in or below the current
directory with the file /tmp/master:find . -name '*.h' -execdir diff -u '{}' /tmp/master ';'
Best Answer
-path
works exactly like-name
, but applies the pattern to the entire pathname of the file being examined, instead of to the last component.-prune
forbids descending below the found file, in case it was a directory.Putting it all together, the command
$HOME
.$HOME/$dir_name
it won't go below it ("prunes" the subdirectory).-o
) if it finds a file matching*$file_suffix
copies it into$HOME/$dir_name/
.The idea seems to be make a backup of some of the contents of
$HOME
in a subdirectory of$HOME
. The parts with-prune
is obviously necessary in order to avoid making backups of backups...