3

or "How to handle prefixed folder names?"

Inside a folder I have two (or more) foo_* folders

foo_0
foo_1

What I'm trying to achieve is to

  • perform an action if there's 1 or more foo_* folders
  • Use a wildcard *

Currently I'm doing it this way (going directly to check if directory foo_0 exists):

prefix=foo_

if [ -d "./${prefix}0/" ]; then
  printf "foo_0 folder found!"
  # delete all foo_* folders
fi

Having directories 0-to-N so the above works, but i'm not sure I'll always have a foo_0 folder...

I'd like to do use a wildcard:

prefix=foo_

if [ -d "./${prefix}*/" ]; then                 # By using wildcard...
  printf "One or more foo_* folders found!"     # this never prints
  # delete all foo_* folders
fi

I've read that a wildcard * inside quotes loses its powers, but placing it outside quotes throws :

if [ -d "./${prefix}"* ]  <<< ERROR: binary operator expected

Or is it possible to use some sort of regex like? ./foo_\d+ ?


The only solution I don't (arguably) like, is by using set

set -- foo_*
if [ -d $1 ]; then
  printf "foo_* found!"
fi

but it wipes program arguments.
Is there any other nice solution to this I'm missing?

Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313

1 Answers1

1

I think a nice solution for pretty much all such cases is to use ls in the test, in that it often works quite simply:

if [ -n "$(ls -d foo_*)" ]; then ... If you want to do more regexp-like matching you can shopt -s extglob and then match with ls foo_+([0-9]).

There's also an all-bash solution using several shell options, but it's not as easy to remember, so I'll leave that to another poster ;-)

EDIT: As @PesaThe pointed out, using ls foo_* would fail if there's only one empty matching directory, as just the empty contents of that directory would get listed and ls foo_* would not only match directories, so it's preferable to use -d.

Johannes Riecken
  • 2,301
  • 16
  • 17
  • my bad, it should have been `if [ -n "$(ls foo_*)" ];then printf "One or more foo_* folders found!";fi`, as it tests if the output of `ls` is non-empty. – Johannes Riecken Mar 05 '18 at 02:14
  • It won't fail if the directories are empty and also won't fail if there are no matches, although it will produce a warning when there are no matches, which can be turned off with `ls foo_* 2>/dev/null` – Johannes Riecken Mar 05 '18 at 03:15
  • 1
    @PesaThe You're right, thanks for pointing that out. I've edited my answer. – Johannes Riecken Mar 05 '18 at 03:31
  • [Don't use `ls` in scripts.](https://mywiki.wooledge.org/ParsingLs) – tripleee Mar 05 '18 at 04:34
  • @tripleee Could you elaborate how using `ls` here will cause problems with weird filenames? Isn't it just like parsing parts of an HTML file, where it's usually a bad idea to use a regexp, but where there are also some use cases where the frowned upon approach will produce much cleaner and easier code? – Johannes Riecken Mar 05 '18 at 05:07
  • I agree that it's probably merely unnecessary here. I tried to think of a scenario where you would want to see the number of matches separately from the action of operating on the matches, but it seems like a rather esoteric corner case. And if you are looping over a wildcard anyway, just `test -e "$file" || continue` at the top of the loop. – tripleee Mar 05 '18 at 05:12