Ls with glob not working in a bash script

bashcommand line

I need to list all the sub directories of a directory excluding those that match any of a list given as an argument: "SUBDIR1,SUBDIR2,…,SUBDIRN".

I came with the solution (from many sources) of using ls with a glob pattern. To test the concept I tried in the command line the following sequence which seems to work:

DIR="/path/to/dirs"
EXCLUDELIST="subdir1,subdir2"
#transform in a glob pattern for excluding given subdirectories
EXCLUDE="!(${EXCLUDELIST//,/|})"
LIST=$(cd $DIR && ls -l -d $EXCLUDE | grep -E "(^d)" | awk '{print $9}')

However, when I put it in a bash script unmodified I get this error

ls: cannot access !(subdir1|subdir2): No such file or directory

What am I doing wrong when putting this code in the script?

Best Answer

Dennis told you why your script is failing but I'd like to suggest an easier (and safer) way of doing this. Parsing ls is almost always a bad idea, it can easily break on file names with spaces or new lines or other strange characters and is not portable across LOCALE settings. Also, your command is very complex, involving multiple steps. Why not do it all in find?

DIR="/path/to/dirs"
EXCLUDELIST="subdir1,subdir2"
## Build the regular expression
EXCLUDE="${EXCLUDELIST//,/|.*}"
LIST=$(find "$DIR" -type d -regextype posix-awk -not -regex ".*$EXCLUDE.*")

By the way, your script will fail as you have it written because you build the glob before cd-ing into $DIR so it will be built with respect to the contents of your current directory.

Related Question