I have a simple bash script it will take arguments from a file that has quotes.
my file arg.txt would be this -lt "*.txt"
my script file would be LS_ARG=`cat arg.txt` ls $LS_ARG
it does not run properly: sh -x ./arg.sh ++ cat arg.txt + LS_ARG='-lt "*.txt"' + ls -lt '"*.txt"' ls: cannot access "*.txt": No such file or directory
How do I resolve that ? If the quotes are not in my file it all works fine. I think its because it looks like the extra single quotes it puts around the "*.txt" - or - '"*.txt"' - how do I do this ? This is just a short example of my larger need.
Thanks,
Jerry
On Thu, 16 May 2019, Jerry Geis wrote:
I have a simple bash script it will take arguments from a file that has quotes.
my file arg.txt would be this -lt "*.txt"
my script file would be LS_ARG=`cat arg.txt` ls $LS_ARG
it does not run properly: sh -x ./arg.sh ++ cat arg.txt
- LS_ARG='-lt "*.txt"'
- ls -lt '"*.txt"'
ls: cannot access "*.txt": No such file or directory
How do I resolve that ? If the quotes are not in my file it all works fine. I think its because it looks like the extra single quotes it puts around the "*.txt" - or - '"*.txt"' - how do I do this ? This is just a short example of my larger need.
In general, shell utilities won't expand a wildcard within quotes (double or single). As I think you've discovered, this works fine:
echo '-lt *.txt' > argfile ls $(< argfile)
I think you're going to need to provide a test case where the quotes are actually required.
On Thu, 2019-05-16 at 12:57 -0400, Jerry Geis wrote:
I have a simple bash script it will take arguments from a file that has quotes.
my file arg.txt would be this -lt "*.txt"
my script file would be LS_ARG=`cat arg.txt` ls $LS_ARG
it does not run properly: sh -x ./arg.sh ++ cat arg.txt
- LS_ARG='-lt "*.txt"'
- ls -lt '"*.txt"'
ls: cannot access "*.txt": No such file or directory
How do I resolve that ? If the quotes are not in my file it all works fine. I think its because it looks like the extra single quotes it puts around the "*.txt" - or - '"*.txt"' - how do I do this ?
I think it's to do with when the wildcard * is expanded. The expansion is not done by 'ls', it is done by the shell - so when you do 'ls *', ls doesn't see just the single argument '*', it sees multiple arguments consisting of the filenames. Using a simpler example, a shell script 'c' is:
#!/bin/bash echo $# echo "1:" $1 echo "2:" $2
i.e. it displays the number of and the first two arguments:
$ ./c * 4 1: a 2: a2
So there are 4 arguments (not just one) because there are four files in the directory.
You can turn off the expansion (aka globbing) with 'set -f'
$ set -f ; ./c * ; set +f 1 1: * 2:
(But you also have to turn off globbing in the './c' script as well - that's a subshell and globbing isn't inherited
#!/bin/bash set -f echo $# echo "1:" $1 echo "2:" $2
if you don't turn off globbing in the script, when $1 - which contains '*' - is echoed, it is expanded at that point.)
Putting quotes around the "*" stops the expansion - this is with globbing turned off in the script:
$ ./c "*" 1 1: * 2:
Similarly, using ls: $ ls * a a2 arg.txt c $ set -f ; ls * ; set +f ls: cannot access '*': No such file or directory $ ls "*" ls: cannot access '*': No such file or directory
I don't know how this affects what you are trying to do though!
BTW, the single quotes you see when tracing the shell script is, I think, just for display purposes, they aren't actually part of the variables and are there just to show what is a single entity if there is any doubt.
P.