1

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.

5
  • What command do you see? An what happens when you simplify the makefile? Commented Apr 6, 2019 at 2:35
  • @Beta I updated the question simplifying the most I can. Commented Apr 6, 2019 at 3:10
  • ...And then you found the bug with ease. Now you understand why we advise people to simplify their code. Commented Apr 6, 2019 at 3:32
  • @Beta, thanks for helping! If you know why it worked, you could post as an answer! Commented Apr 6, 2019 at 4:12
  • 1
    Bash expands unquoted wildcards. Without the double-quotes, the command rm *aux becomes rm main.aux, but with the double-quotes rm tries to remove a file named *.aux, and there's no such file. Commented Apr 7, 2019 at 0:31

1 Answer 1

2

I managed to fix it by changing:

 rm -vf "$$full_expression"; \ 

To:

 rm -vf $${full_expression}; \ 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.