I need to get the number of the contents of a directory that is a git repository.
I have to get the number of:
1) Other directories inside the directory I am currently iterating (and the other sub-directories inside them if they exist)
2) .txt files inside the directory and its sub-directories
3) All the non-txt files inside the directory and its sub-directories
In all the above cases I must ignore the .git directory, along with all the files and directories that are inside of it.
Also I must use bash script exclusively. I can't use another programing language.
Right now I am using the following commands to achieve this:
To get all the
.txtfiles I use :find . -type f \( -name "*.txt" \). There are no.txtfiles inside.gitso this is working.To get all the
non-txtfiles I use:find . -type f \( ! -name "*.txt" \). The problem is that I also get all the files from.gitand I don't know how to ignore them.To get all the
directoriesandsub-directoriesI use:find . -type d. I don't know how to ignore the.gitdirectory and it's sub-directories
CodePudding user response:
The easy way is to just add these extra tests:
find . ! -path './.git/*' ! -path ./.git -type f -name '*.txt'
The problem with this is ./.git is still traversed, unnecessarily, which takes time.
Instead, -prune can be used. -prune is not a test (like -path, or -type). It's an action. The action is "don't descend the current path, if it's a directory". It must be used separately to the print action.
# task 1
find . -path './.git' -prune -o -type f -name '*.txt' -print
# task 2
find . -path './.git' -prune -o -type f ! -name '*.txt' -print
# task 3
find . -path './.git' -prune -o -type d -print
- If
-printisn't specified,./.gitis also printed as the default action. - I used
-path ./.git, because you said "the.gitdirectory". If for some reason there are other.gitdirectories in the tree, they will be traversed and printed. To ignore all directories in the tree named.git, replace-path ./.gitwith-name .git.
CodePudding user response:
Sometimes writing a bash loop is more clear than a one-liner
for f in $(find .); do
if [[ -d $f && "$f" == "./.git" ]]; then
echo "skipping dir $f";
else
echo "do something with $f";
fi;
done
