0

I'm pretty inexperienced to globbing in general. How would one go about writing a glob pattern that matches filenames not starting with, say, "ab" but still need a length of at least 2? i.e. "start with something 2-letter string other than "ab"" This is a homework question, and only basic bash globs are allowed, and must work with "echo <glob here>".

Note: the question verbatim is

(Non-hidden) files in the current directory whose names contain at least two characters, but do not start with ab.

printed on paper. I'm pretty sure I didn't misunderstand anything. The requirements are

For each of the following file search criteria, provide a globbing pattern that matches the criterion. Your answer in each case should be a text file with the following format:

echo <pattern>

My current attempt is echo {a[!b]*,[!a.]?*} but somehow it gets no points with the automatic grader which actually runs your file against a test case automatically without human intervention.

ithisa
  • 752
  • 1
  • 8
  • 25
  • 2
    Due to the odd formulation of the question, I suspect your teacher is looking for the answer `[^a][^b]*`. It's a common mistake, and several correct (but necessarily non-basic) solutions are given in the answers. – that other guy May 15 '13 at 00:15
  • 1
    @thatotherguy, I think `[^a]?*` is a better answer, less wrong anyway – perreal May 15 '13 at 00:30
  • 2
    @perreal: he knows that, but he also assumes (like I do) the answer to this question actually doesn't exist, and offers up some misconception the _teacher_ may have about what the answer should be, which is actually wrong. – Wrikken May 15 '13 at 00:35
  • Grading is all automatic by running your glob against a test cases. A program marks your programs (this is University of Waterloo, where the robot takeover is starting xD). My current glob is {a[!b]*,[!a.]?*} which I think is pretty smart but gets 0/1. I'll update my post. – ithisa May 15 '13 at 01:45
  • @EricDong: it would still give back a `a[!b]*` when there are not files starting with a + a non b character. – Wrikken May 15 '13 at 14:14

4 Answers4

4

For a single letter, this would do:

$ echo [!a]?*

However, for 2 letters (and assuming files can also start with numbers or punctuation or all kinds of other things), I can only think of this without resorting to shopt:

$ GLOBIGNORE=ab* 
$ echo *

Well, now, technically, this would work:

$ echo [!a]?* [a][!b]*

BUT this would leave a nasty [a][!b]* in our results if there are no files starting with an a+1 or more extra characters, which would not only be undesirable, but even considered a bug in any application, so on that grounds I would not consider it a valid answer. To omit that [a][!b]*, we have to resort to nullglob (and if extglob isn't allowed, nullglob probably isn't either):

$ shopt -s nullglob
$ echo [!a]?* [a][!b]*

Fwiw, extglob would be:

$ shopt -s extglob

$ echo !(ab*) That previous answer would match files with less then 2 characters, so like @perreal says:

$ @([^a]?|?[^b])*
Wrikken
  • 69,272
  • 8
  • 97
  • 136
  • extglob not allowed. Must use vanilla globs that go immediately after echo with no pipes etc. – ithisa May 15 '13 at 00:15
  • 1
    @EricDong: well, with vanilla globs the `GLOBIGNORE` is all I can give you. I seriously doubt it's possible without that or a `shopt`, unless you use the `echo [!a]?* [a][!b]*` and you don't mind `[a][!b]*` is in the results if there are no files starting with `a`. – Wrikken May 15 '13 at 00:27
  • Well, yes, I could elaborate why I only use it with a `nullglob` for completeness sake indeed. Editing... – Wrikken May 15 '13 at 00:43
  • In the academy you can assume anything, anyway – perreal May 15 '13 at 00:48
  • Well, the OP mentions that as a file, but mentions `test cases`, suggesting multiple file lists to test against... – Wrikken May 15 '13 at 00:52
2

Starting with "a" or "b" OR with "ab"? For the later:

ab*

Needless to say, you have to specify a path that resolves (relative or absolute):

/path/to/ab*

To your updated question:

{b,c,d,e,f...}{a,c,d,e,f...}*

Should work, note that ... is not actually valid, but I won't write the whole alphabet here. :P

Alix Axel
  • 151,645
  • 95
  • 393
  • 500
  • Sorry, I asked the wrong question. I massively edited my post now. – ithisa May 14 '13 at 23:47
  • @EricDong: Updated again to allow filenames that start with `ba`. – Alix Axel May 14 '13 at 23:54
  • @EricDong: True. Then all I can think of is something like `{ac,..,az,ba,bb,bc,..,zz}*` but I highly doubt they would ask you for such a convulsed solution if no cleaner alternative exists. I don't know, sorry. – Alix Axel May 15 '13 at 00:00
  • @EricDong: Do you have access to extglob http://stackoverflow.com/a/217017/89771? – Alix Axel May 15 '13 at 00:04
  • No. We can only do echo fill in the blank. In fact we submit a file containing the fill in the blank part which is then automatically graded by running it against test cases. – ithisa May 15 '13 at 00:11
  • @EricDong: Dammit. I'm sleepy. Ignore it and have a nice night. Good luck! – Alix Axel May 15 '13 at 00:36
1
shopt -s extglob         # turn on extended globbing
echo @([^a]?|?[^b])*
perreal
  • 94,503
  • 21
  • 155
  • 181
  • extglob not allowed. We need to make it work with something that you put immediately after echo. ; not allowed and not a big shell script. – ithisa May 15 '13 at 00:15
  • Ah, you're right my `extglob` did not meet the requirement of 'minimal 2 letters'. – Wrikken May 15 '13 at 00:38
0

My original echo {a[!b]*,[!a.]?*} is correct works very well. The teacher actually set up the test cases wrong, so everybody got marked incorrectly and got a remark just now.

ithisa
  • 752
  • 1
  • 8
  • 25
  • Since {a[!b]*,[!a.]?*} expands immediately (brace expansion happens before other expansions) to a[!b]* [!a.]?* which is actually shorter, I can see no reason to use brace expansion in this way. If you wanted to express the fact that both subpatterns have a common suffix, {a[!b],[!a.]?}* expands to the same thing as your original and is also shorter, though still longer than its expansion. – flabdablet Oct 20 '17 at 17:16