1

I would like to capture a directory that contains spaces in a bash variable and pass this to the ls command without surrounding in double quotes the variable deference. Following are two examples that illustrate the problem. Example 1 works but it involves typing double quotes. Example 2 does not work, but I wish it did because then I could avoid typing the double quotes.

Example 1, with quotes surrounding variable, as in the solution to How to add path with space in Bash variable, which does not solve the problem:

[user@machine]$ myfolder=/home/username/myfolder\ with\ spaces/
[user@machine]$ ls "$myfolder"
file1.txt file2.txt file3.txt

Example 2, with quotes part of variable, which also does not solve the problem. According to my understanding, in this example, the first quote character sent to the ls command before the error is thrown:

[user@machine]$ myfolder=\"/home/username/myfolder\ with\ spaces/\"
[user@machine]$ ls $myfolder
ls: cannot access '"/home/username/myfolder': No such file or directory

In example 2, the error message indicates that the first double quote was sent to the ls command, but I want these quotes to be interpreted by bash, not ls. Is there a way I can change the myfolder variable so that the second line behaves exactly as the following:

[user@machine]$ ls "/home/username/myfolder with spaces/"

The goal is to craft the myfolder variable in such a way that (1) it does not need to be surrounded by any characters and (2) the ls command will list the contents of the existing directory that it represents.

The motivation is to have an efficient shorthand to pass long directory paths containing spaces to executables on the command line with as few characters as possible - so without double quotes if that is possible.

markp-fuso
  • 28,790
  • 4
  • 16
  • 36
mangi07
  • 23
  • 4
  • 1
    You can use `eval ls $myfolder`, but that adds 5 characters to save 2 quotes. – Barmar Jul 29 '21 at 00:54
  • Thank you for this tip! I guess I could create an alias for "eval ls" such as: alias lse="eval ls" and then use that as: lse $myfolder – mangi07 Jul 29 '21 at 01:04
  • 1
    Note that `eval` will also process any other shell metacharacters, not just quotes. If there are `;` characters, they will separate it into multiple commands, and they'll be executed. – Barmar Jul 29 '21 at 01:06
  • 2
    E.g. `myfolder="foo;rm *"` will remove everything. – Barmar Jul 29 '21 at 01:06
  • 1
    Double-quoting variables is the only solution that works reliably. Unless you want to switch to zsh... – Gordon Davisson Jul 29 '21 at 01:07

1 Answers1

-1

Assuming some 'extra' characters prior to the ls command is acceptable:

$ mkdir /tmp/'myfolder with spaces'
$ touch /tmp/'myfolder with spaces'/myfile.txt

$ myfolder='/tmp/myfolder with spaces'
$ myfolder=${myfolder// /?}               # replace spaces with literal '?'
$ typeset -p myfolder
declare -- myfolder="/tmp/myfolder?with?spaces"

$ set -xv
$ ls $myfolder
+ ls '/tmp/myfolder with spaces'
myfile.txt

Here's a fiddle

Granted, the ? is going to match on any single character but how likely is it that you'll have multiple directories/files with similar names where the only difference is a space vs a non-space?

markp-fuso
  • 28,790
  • 4
  • 16
  • 36
  • 1
    Thank you, @markp-fuso, for this. It seems there is no easier built-in way to do this in bash, but since this does technically answer my question, I'll mark it as the accepted answer. And it would work for my current use case, because I'm not going to have multiple matches. Clever use of question marks and character substitution -- thanks! – mangi07 Jul 30 '21 at 03:10