1

I'm trying to put a third check whether the directory contains only hidden files:

if [ ! "$(ls -A "$dir")" ]; then
  echo "Specified directory is empty"
  exit 1
elif [[ -z "$(find "$dir" -maxdepth 1 -type f)" ]]; then
  echo "Specified directory contains only subdirectories and no files"
  exit 1
elif [[ -z "$(find "$dir" -maxdepth 1 -type f | grep -v '"$dir"/.*')" ]]; then
  echo "Specified directory contains only hidden files"
  exit 1
fi

The third check is what is not working. I tried getting a list of all files that don't match '.*' and checking if it's empty with -z, but it always tests true. Do you have an idea?

shin
  • 333
  • 3
  • 11
  • 1
    See: [Difference between single and double quotes in bash](http://stackoverflow.com/q/6697753/3776858) – Cyrus Oct 22 '20 at 11:12
  • `grep -v '"$dir"/.*'` - do `'!' -name '.*'`. `if directory contains only hidden files and no directories` if a directory has only files, it has no directories. – KamilCuk Oct 22 '20 at 11:17

1 Answers1

1

Generally don't use ls in scripts.

Assuming you have the default values for nullglob etc,

files=(./*)
if [[ "${files[@]}" = './*' ]]; then
  echo "Specified directory is empty" >&2
  exit 1
fi
dirs=(./*/)
if [[ "${#dirs[@]}" = "${#files[@]}" ]]; then
  echo "Specified directory contains only subdirectories and no files" >&2
  exit 1
fi
hidden=(./.*)
if [[ "${#hidden[@]}" = "${#files[@]}" ]]; then
  echo "Specified directory contains only hidden files" >&2
  exit 1
fi

There is an obvious race condition here, in that another process could add a new hidden file after files gets assigned, but before hidden gets assigned, for example.

The use of arrays makes this Bash-only; this should be obvious, but many beginners are confused about the difference between sh and bash.

The immediate error in your attempt is that '"$dir"/.*' is in single quotes, and so gets interpreted verbatim (and even if you fixed the quoting, . in a regex matches any character, not a literal dot). But more broadly, it seems excessive to use find when the shell itself can tell you what files you have.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Thank you! Yes, the problem was the regex (and the qotes) indeed. I solved it like this: [[ -z "$(find "$dir" -maxdepth 1 -type f | grep -v ""$dir"/\..*")" ]] I guess it's overkill, so I'll probably try your solution. What does >&2 do if I can ask? – shin Oct 22 '20 at 11:52
  • 1
    Diagnostic messages should be displayed on standard error, not standard output. It makes less of a difference here, but it's good practice. – tripleee Oct 22 '20 at 11:57