2

I'm trying to write a shell script, and to make it more or less readable, i decided to bring a part of my commands into environment variables:

#!/bin/bash
# Variables

name_expression="-type d \( -name .folder1 -o -name .wildcardfolder* -o -name .folder2 \)"

# Commands

find /root/ -maxdepth 1 "$name_expression" -execdir rm -rf {} \;
find /home/ -maxdepth 2 "$name_expression" -execdir rm -rf {} \;

The problem is that if i try to run this shell, many symbols are wrapped with quotes:

bash -x ./my_shell.sh 
+ name_expression='-type d \( -name .android -o -name .AndroidStudio* -o -name .gradle \)'
+ find /home/ /root/ -maxdepth 2 '-type d \( -name .folder1 -o -name .wildcardfolder* -o -name .folder2 \)' -execdir rm -rf '{}' ';'
find: unknown predicate `-type d \( -name .folder1 -o -name .wildcardfolder* -o -name .folder2 \)'

Is there any way to pass this variable without being modified?

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232

2 Answers2

3
name_expression=( -type d \( -name .folder1 -o -name .wildcardfolder\* -o -name .folder2 \) )

find /root/ -maxdepth 1 "${name_expression[@]}" -execdir rm -rf {} \;

Instead of a string parameter which would have to be unquoted in order for the command to see several parts, this uses an array parameter. That way both the splitting and the quoting can be controlled (not completely i.e. per part but in a suitable way for this task).

An alternative which allows complete control would be the use of eval but that would make the rest of the command line more complicated.

Hauke Laging
  • 90,279
  • The backslash in .wildcardfolder\* doesn't do what you think it does. The glob can still be expanded (to files with a backslash in the name) and the -name primary won't match the way it was intended. – Wildcard Sep 06 '17 at 21:54
  • @Wildcard I have not found an explanation for it but bash 4.4.12 does not expand touch 'bar\_' ; testvar="bar\*" ; echo $testvar bar\\*. Does not remove the \\ either. Maybe a shell bug. – Hauke Laging Sep 06 '17 at 22:45
  • Interesting. You're right, it doesn't expand. However, it does get treated as an escape by find so that find will only match a literal * character for that position. So this command still won't work. – Wildcard Sep 06 '17 at 23:00
  • While I personally agree this is the proper way to address the issue, some explanation would be good so people understand what this is doing. – phemmer Sep 06 '17 at 23:58
  • (Note: the comments above refer to the earlier revision of this answer, but they contain interesting relevant technical data so shouldn't be deleted IMO.) – Wildcard Sep 07 '17 at 21:33
2

A modified version that avoids potentially hazardous glob expansions:

cleanupdir() {
  # args should be dirname, maxdepth
  find "$1" -maxdepth "$2" -type d \( -name .folder1 -o -name '.wildcardfolder*' -o -name .folder2 \) -execdir rm -rf {} \;
}

cleanupdir /root 1
cleanupdir /home 2
Wildcard
  • 36,499