This works great:

ls /path/{foo,bar}/

Now, what if I want to effectively do:

cp /path/foo/bunch/of/stuff/foo.txt /path/bar/bunch/of/stuff/bar.txt

Is there some short-hand I can do on a single command line?

I.e. kinda like cp /path/{foo,bar}/file.txt but where there are two substitutions that must be done simultaneously?

Effectively, I want multiple coupled brace expansions that do not yield all possible combinations.


The substitution can include /:

cp /path/{foo/foo,bar/bar}.txt

is equivalent to

cp /path/foo/foo.txt /path/bar/bar.txt

An alternative approach would be to search-and-replace; this works as long as "foo" doesn't contain slashes:

set /path/foo/bunch/of/stuff/foo.txt; cp $1 ${1//foo/bar}

One way is to use history interaction, but for the current line (!#):

$ echo /path/foo/bunch/of/stuff/foo.txt  !#:1:gs/foo/bar/
echo /path/foo/bunch/of/stuff/foo.txt  /path/bar/bunch/of/stuff/bar.txt
  • !#, as already said, refers to the current line
  • :1 to the first word
  • :s/foo/bar substitutes bar for foo
  • g is a modifier which makes the substitution over the whole line
  • One interesting side-effect of this approach is that the expanded line is what ends up stored in the shell's history. Feb 17 '15 at 23:10
  • @StephenKitt oh, history interaction is never directly recorded in the history, is it? (As in, only the effects are seen in the history)
    – muru
    Feb 17 '15 at 23:14
  • I think so, yes; at least a quick look through the bash manual didn't reveal any option to allow recording the pre-history-expansion version of a command. Feb 17 '15 at 23:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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