0

I am trying to open two files with the same filename prefix at the same time using `open *. Here is a demonstration:

mathewlewis@mathewlewis-ThinkPad-X220:~/Documents/bug/testing$ touch asdf1.txt asdf2.txt
mathewlewis@mathewlewis-ThinkPad-X220:~/Documents/bug/testing$ open asdf*
xdg-open: unexpected argument 'asdf2.txt'
Try 'xdg-open --help' for more information.
mathewlewis@mathewlewis-ThinkPad-X220:~/Documents/bug/testing$ open asdf1.txt
mathewlewis@mathewlewis-ThinkPad-X220:~/Documents/bug/testing$ open asdf2.txt 
mathewlewis@mathewlewis-ThinkPad-X220:~/Documents/bug/testing$ 

As you can see in the above, I can't open both files at the same time, but I can open them individually fine. In case this is relevant, I have set my default text editor to sublime text. Also I am running ubuntu version 22.04 as you can see in the following:

mathewlewis@mathewlewis-ThinkPad-X220:~/Documents/bug/testing$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04 LTS
Release:    22.04
Codename:   jammy
mathewlewis@mathewlewis-ThinkPad-X220:~/Documents/bug/testing$ 

I am able to use * to do many commands at the same time usually. For example, I can do cat asdf* to print both files, however open won't work this way. I am new to linux and am coming from mac where this is possible. I'd like to know why I can't do this on ubuntu and how I can fix this.

Mathew
  • 145

2 Answers2

1

It's the shell who expands (or not) asdf*. When you invoke open asdf*, open gets the result of the expansion. In your case it gets at least two operands.

So it's a matter whether a single open can handle multiple operands or not. open in Ubuntu cannot; apparently (I trust your word) open in Mac can.

A straightforward fix is to run one open per file in a loop:

for f in asdf*; do open "$f"; done

Since open does not wait for the program it runs to close, many of them may be spawned asynchronously, possibly too fast. I totally don't know if open with multiple arguments in Mac does it this way. In my tests (in Kubuntu) with many text files, kate (text editor) was usually called for the second time too soon after the first time, resulting in at least two separate Kate windows, and only then multiple tabs in one of the windows. Ideally it would be one window and many tabs there. A simple workaround is to sleep for a while between opens:

for f in asdf*; do open "$f"; sleep 1; done

But:

  • this (or any sleep N) still does not guarantee opens will occur slow enough for an arbitrary utility and system load at the time;
  • if asdf* expands to many, many names, the entire loop may take a long time unnecessarily.

The simplest way for open to support multiple operands is to run an equivalent loop internally. The problems we noticed may be reasons why this hasn't been implemented. It's my guess though.


It may be useful to build a shell function (or an equivalent script) and "overload" open, like this:

open() {
   for f do command open "$f"; done
}

(include sleep 1 if you want).

There's one potential problem with this approach: a command like open --some-option foo bar will run open --some-option, open foo and open bar instead of open --some-option foo and open --some-option bar you would probably want. To fix this in general, the function would need to parse its arguments and "understand" them like the real open does. Obviously it would be better if the real open did all the job internally.

On the other hand man 1 open (in my Kubuntu) only mentions --help, --manual and --version as exclusive options; none of them can be specified with a file/URL operand. This means parsing options in our function is pointless because open --some-option foo is invalid anyway. The function is better as it is.

0

GNU parallel is probably overkill for this particular use case, but it can do this:

parallel xdg-open {} ::: asdf*.txt