I got this script which reads a delimited part of my .gitignore file and remove all files after the given mark # #:
# https://stackoverflow.com/questions/55527923/how-to-stop-makefile-from-expanding-my-shell-output RAW_GITIGNORE_CONTENTS := $(shell while read -r line; do printf "$$line "; done < ".gitignore") GITIGNORE_CONTENTS := $(shell echo "$(RAW_GITIGNORE_CONTENTS)" | sed -E $$'s/[^\#]+\# //g') # https://stackoverflow.com/questions/4210042/exclude-directory-from-find-command DIRECTORIES_TO_CLEAN := $(shell /bin/find -not -path "./**.git**" -not -path "./pictures**" -type d) clean: # https://stackoverflow.com/questions/10586153/split-string-into-an-array-in-bash # https://stackoverflow.com/questions/11289551/argument-list-too-long-error-for-rm-cp-mv-commands readarray -td' ' GARBAGE_DIRECTORIES <<<"$(DIRECTORIES_TO_CLEAN) "; \ unset 'GARBAGE_DIRECTORIES[-1]'; \ declare -p GARBAGE_DIRECTORIES; \ readarray -td' ' GARBAGE_EXTENSIONS <<<"$(GITIGNORE_CONTENTS) "; \ unset 'GARBAGE_EXTENSIONS[-1]'; \ declare -p GARBAGE_EXTENSIONS; \ for filename in "$${GARBAGE_DIRECTORIES[@]}"; \ do \ arraylength="$${#GARBAGE_EXTENSIONS[@]}"; \ printf 'Cleaning %s extensions on %s\n' "$${arraylength}" "$$filename"; \ for extension in "$${GARBAGE_EXTENSIONS[@]}"; \ do \ [[ ! -z "$$filename" ]] || continue; \ [[ ! -z "$$extension" ]] || continue; \ full_expression="$${filename}/$${extension}" ;\ printf '%s\n' "$$full_expression"; \ rm -v "$$full_expression"; \ done; \ done; Running it with the following .gitignore file:
*.txt *.var # Comment # *.aux The rm command is not expanding the wildcards and keeps telling me rm: cannot remove './*.aux': No such file or directory and do not remove the *.aux files from the ./ directory.
Update
After asked on a comment by @Beta, I simplified the Makefile to this:
GITIGNORE_CONTENTS := "*.aux" "*.lof" DIRECTORIES_TO_CLEAN := "./setup/cache" "./setup/cache/chapters" clean: readarray -td' ' GARBAGE_DIRECTORIES <<<"$(DIRECTORIES_TO_CLEAN) "; \ unset 'GARBAGE_DIRECTORIES[-1]'; \ declare -p GARBAGE_DIRECTORIES; \ readarray -td' ' GARBAGE_EXTENSIONS <<<"$(GITIGNORE_CONTENTS) "; \ unset 'GARBAGE_EXTENSIONS[-1]'; \ declare -p GARBAGE_EXTENSIONS; \ for filename in "$${GARBAGE_DIRECTORIES[@]}"; \ do \ arraylength="$${#GARBAGE_EXTENSIONS[@]}"; \ printf 'Cleaning %s extensions on %s\n' "$${arraylength}" "$$filename"; \ for extension in "$${GARBAGE_EXTENSIONS[@]}"; \ do \ [[ ! -z "$$filename" ]] || continue; \ [[ ! -z "$$extension" ]] || continue; \ full_expression="$${filename}/$${extension}" ;\ printf '%s\n' "$$full_expression"; \ rm -vf "$$full_expression"; \ done; \ done; Which results on this output after running it:
$ make readarray -td' ' GARBAGE_DIRECTORIES <<<""./setup/cache" "./setup/cache/chapters" "; \ unset 'GARBAGE_DIRECTORIES[-1]'; \ declare -p GARBAGE_DIRECTORIES; \ readarray -td' ' GARBAGE_EXTENSIONS <<<""*.aux" "*.lof" "; \ unset 'GARBAGE_EXTENSIONS[-1]'; \ declare -p GARBAGE_EXTENSIONS; \ for filename in "${GARBAGE_DIRECTORIES[@]}"; \ do \ arraylength="${#GARBAGE_EXTENSIONS[@]}"; \ printf 'Cleaning %s extensions on %s\n' "${arraylength}" "$filename"; \ for extension in "${GARBAGE_EXTENSIONS[@]}"; \ do \ [[ ! -z "$filename" ]] || continue; \ [[ ! -z "$extension" ]] || continue; \ full_expression="${filename}/${extension}" ;\ printf '%s\n' "$full_expression"; \ rm -vf "$full_expression"; \ done; \ done; declare -a GARBAGE_DIRECTORIES=([0]="./setup/cache" [1]="./setup/cache/chapters") declare -a GARBAGE_EXTENSIONS=([0]="*.aux" [1]="*.lof") Cleaning 2 extensions on ./setup/cache ./setup/cache/*.aux ./setup/cache/*.lof Cleaning 2 extensions on ./setup/cache/chapters ./setup/cache/chapters/*.aux ./setup/cache/chapters/*.lof More simplification
I reduced to the more simple version it could be:
clean: rm -v "./setup/cache/*.aux"; Running this, also do not remove the files:
$ make rm -v "./setup/cache/*.aux"; rm: cannot remove './setup/cache/*.aux': No such file or directory make: *** [Makefile:3: clean] Error 1 $ ls ./setup/cache/*.aux ./setup/cache/main.aux On above, after running ls, you can see the file still exists and it is there.
rm *auxbecomesrm main.aux, but with the double-quotesrmtries to remove a file named*.aux, and there's no such file.