4

I'm trying to make a bash script that deals with every file in a directory. All of those file names begin with a dot, so they're hidden. When I try to use a wildcard to grab everything in the directory, the wildcard isn't expanding.

My code that loops over it looks like this right now:

#!/bin/bash
shopt -s extglob

for i in "$(pwd)"/*; do
  echo "$i"
done

The output is just /Users/.../*. The wildcard doesn't expand.

This is different than some of the other threads because it deals with hidden files specifically. If I add a file like test to the directory, then it works. I get /Users/.../test.

I tried running this in the terminal by itself as well and got the same result. How do I get the wildcard to expand for hidden files?

2 Answers 2

8

I figured it out! Looking more closely at the documentation for shopt, there's an option called dotglob that can be used to include filenames that begin with a dot!

I added shopt -s dotglob to the beginning of my script and it works now. The output now lists every hidden file and directory (except ./ and ../).

My script now looks like this:

#!/bin/bash
shopt -s extglob
shopt -s dotglob

for i in "$(pwd)"/*; do
  echo "$i"
done
3
  • 3
    Also useful: shopt -s nullglob makes a globbing expression expand to nothing if it matches nothing; "$PWD" holds the same value printed by pwd, but echo "$PWD" lets you save a fork compared to echo "$(pwd)" - in Bash, command substitution is performed using a child process.
    – fra-san
    Commented Aug 26, 2020 at 22:11
  • 2
    @fra-san, $(pwd) (as opposed to $PWD) also doesn't work properly when the path to the current working directory ends in newline characters. Commented Aug 27, 2020 at 8:54
  • 2
    Note that extglob is not necessary here for the expansion of that glob. extglob would b e needed if you wanted to use the extended ksh88 operators like @(...), !(...), *(...)... Commented Aug 27, 2020 at 8:55
2

posix workaround without dotglob

#!/bin/sh

for i in "$PWD"/* "$PWD"/.*
  do
    [ "${i##*/}" = . ] || \
    [ "${i##*/}" = .. ] || \
    [ "${i##*/}" = \* ] || \
    [ "${i##*/}" = .\* ] && continue

    echo "$i"
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .