0

I'm trying to figure out how to work with arguments to my bash script when there are spaces in said arguments.

To distill this problem into the simplest possible, consider a script that simply does an ls with the provided argument...

#!/bin/bash
echo $1
ls $1

Consider the following folder structure:

enter image description here

When I run it with a folder that has no spaces, it works:

$ ./my_ls.sh ~/Documents/Temp/Foo
/Users/user_name/Documents/Temp/Foo
Test

When I attempt to do the same with the folder with a space, I get some errors:

$ ./my_ls.sh "~/Documents/Temp/Bar Baz"
~/Documents/Temp/Bar Baz
ls: Baz: No such file or directory
ls: ~/Documents/Temp/Bar: No such file or directory

I tried using a backslash instead to no avail:

$ ./my_ls.sh ~/Documents/Temp/Bar\ Baz
/Users/user_name/Documents/Temp/Bar Baz
ls: /Users/user_name/Documents/Temp/Bar: No such file or directory
ls: Baz: No such file or directory

How do I refer to folders/files when there are spaces in their names?


I found out that one way to fix the script is to use quotes:

#!/bin/bash
echo $1
ls "$1"

... and when running the script, use backslash escaping (instead of quotes).

However, this seems counterintuitive, since if we know that backslashes are the way to run the script (./my_ls.sh ~/Documents/Temp/Bar\ Baz), why would I use quotes when I run ls (ls "$1")? It seems like these should be consistent here. What am I missing? Are there general best practices when dealing with arguments provided by the user (e.g. always assume they are using backslash quotes, and that arguments that refer to directories might have spaces in them)?


What's even more odd is that when I use quotes with ls via the command line, it fails:

$ ls "~/Documents/Temp/Bar Baz"
ls: ~/Documents/Temp/Bar Baz: No such file or directory

Why, then, is adding quotes in the bash script the way to go?

Senseful
  • 86,719
  • 67
  • 308
  • 465
  • 1
    You can also run `./my_ls.sh "$HOME/Documents/Temp/Bar Baz"`. There are many ways to quote. Choose what you like. – William Pursell Jul 12 '19 at 22:16
  • 1
    The reason `ls "~/Documents..."` fails is that the `~` doesn't get expanded to $HOME – William Pursell Jul 12 '19 at 22:17
  • 1
    Don't worry about how the user passed the argument. Whether the user enters `./my_ls.sh foo\ bar` or `./my_ls.sh "foo bar"`, the first argument will in each case be the string `foo bar` – William Pursell Jul 12 '19 at 22:19
  • You don't have to quote everything, either. `./my_ls.sh ~/Documents/Temp/"Bar Baz"` will work as well. – Tanktalus Jul 12 '19 at 22:20

0 Answers0