Very often, when using the command line or just programming, you want to express some kind of combination that you end up using a for - which is often verbose.

for (int i = 0; i<10; ++i)
    std::cout << "img_" << i << std::endl;

for f in *; do echo "$f"; done

I always wondered if there is some kind of language made to simplify this case? For example:

"mv img_[0~6] imgs"

Would translate to

mv img_0 imgs
mv img_1 imgs
mv img_2 imgs
mv img_3 imgs
mv img_4 imgs
mv img_5 imgs

img_[0~1][0~1] could work for img_00, img_01, img_10, img_11

img_[x:0~2][x] could work for img_00, img_11, img_22


I'm not asking for this particular syntax, just if there is any kind of language/feature ever implemented with the purpose of expressing such combinations as easy as possible?

  • 3
    Ever hear about apl? "It is concise, using symbols rather than words and applying functions to entire arrays without using explicit loops." – Oded Jul 19 '13 at 19:39
  • @Oded SE has eaten all of your time, except a little tiny bit left for snark? and in answer to the question: this wreaks of what people loved perl for. – Jimmy Hoffa Jul 19 '13 at 20:24
  • 1
    Sharing your research helps everyone. Tell us what you've tried and why it didn’t meet your needs. This demonstrates that you’ve taken the time to try to help yourself, it saves us from reiterating obvious answers, and most of all it helps you get a more specific and relevant answer. Also see How to Ask – gnat Jul 19 '13 at 20:57
  • The term you're looking for is globbing – beatgammit Jul 20 '13 at 5:07
  • 1
    @Dokkat - gnat's request isn't too far off base even though it's one of his canned comments for "this question needs more ..." I can't quite tell if you're wanting a regex within a variable usage or if you're wanting on-the-fly matrix math. Or both. You're already picking up one line answers which isn't good for question quality. Please edit and be a bit more clear in what you're seeking and why alternatives you have found haven't answered your question. – user53019 Jul 20 '13 at 11:38

In bash, you can write

mv img_{0..5} imgs/

which is expanded by the shell to

mv img_0 img_1 img_2 img_3 img_4 img_5 imgs/

You can also use a character class:

mv img_[0-5] imgs/

which would only work for those files that already exist and match the expression, while the former expands to all the possibilities even if the files do not exist. The curlies can also pad the expanded number with zeros ({001..030}), reverse the order ({z..a}) or generate combinations ({a..z}{0..5}).

| improve this answer | |
  • 1
    The brace expression can also do padding: echo a{001..100} and combinations: echo {0,1}{0,1}{0,1} – glenn jackman Jul 19 '13 at 20:16
  • Oh, what a coincidence, I had no idea that existed and it is so similar to what I needed. Very cool, glad I've asked. Is there a way to use the same arg twice? img_{x:0..2}_{x} -> img_0_0 img_1_1 img_2_2 – MaiaVictor Jul 20 '13 at 6:41
  • I think you are wrong about the zero padding though. It didn't work here. – MaiaVictor Jul 20 '13 at 6:44
  • @Dokkat: It might depend on the version of bash. Works in 4.2.24. – choroba Jul 21 '13 at 16:59

To answer your immediate concern, bash can do some range-based actions on existing files.

$ ls
sample1.txt  sample2.txt  sample3.txt  sample4.txt  samples

$ mv sample[1-3].txt samples/

$ ls *

sample1.txt  sample2.txt  sample3.txt

But there is a bigger trend at play here. Array programming tries to get away from explicit loops. It was really pushed by APL in the beginning and is now common in many mathematical languages like MATLAB or Mathematica. For example, I can add two numerical arrays with a simple

c = a + b

Likewise, list comprehension uses set notation to build an array. This is a common feature in many languages today, including Python and Haskell.

S = [2 * x for x in range(101) if x ** 2 > 3]

Within the realm of shell scripting, I can use xargs to execute a command on multiple inputs.

hg st | cut -d ' ' -f 2 | xargs rm     # delete my leftovers from Mercurial

In the world of databases, SQL can perform queries and updates on an entire column.

select sym from stocks where price < 20.0 order by sym;

And lastly, recursion obviates loops by defining an entity in terms of itself:

fac 0 = 1
fac x = x * fac (x-1)

So there are lots of examples where languages have gone away from explicit iterations in favor of declarative structures.

| improve this answer | |
  • Recursion doesn't obviate looping. It just describes it in a different way. – Donal Fellows Jul 20 '13 at 11:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.