Bash remove quotes for String argument - string

I need to execute a command in bash that takes a constructed argument. The string argument needs to be passed without quotations. How do I remove the quotes?
This does not work:
Tracks='bark.mov'
TrackDir='~/soundtracks/'
TrackPath=$TrackDir$Track
omxplayer -o local $TrackPath
This does not work:
omxplayer -o local '~/soundtracks/bark.mov'
This does work:
omxplayer -o local ~/soundtracks/bark.mov

Tilde expansion only works outside of quotes. Get rid of the quotes when defining the variables, but do include quotes when expanding them.
Tracks=bark.mov
TrackDir=~/soundtracks/
TrackPath=$TrackDir$Track
omxplayer -o local "$TrackPath"

You need to leave the ~ unquoted so that the shell can expand it to the user's home directory. Further, it's better practice to add the path separator when you join the two, to make it explicit. Having two adjacent / in the path doesn't hurt.
Tracks=bark.mov
TrackDir=~/soundtracks/
TrackPath=$TrackDir/$Track
omxplayer -o local "$TrackPath"

Related

How do I run sed in TCL

I am trying to use TCLs builtin exec procedure to run the following sed shell command:
sed -i 's/"VALUE.${name}">.*</"VALUE.${name}">${value}</' ${dir}/imp.xml
However when I pass it to exec tcl errors out with
sed: -e expression #1, char 1: unknown command: `''
no idea how to interpret this.
I tried escaping the exec string:
exec {sed -i 's/"VALUE.${name}">.*</"VALUE.${name}">${value}</' ${dir}/imp.xml}
However this prevents the tcl variables from being expanded inside of the string.
Does anyone know what I need to do to get tcl to exec this sed program?
(my shell is csh if that is relevant)
The final solution involved 2 changes to the command string,
Escape all the double quote characters, (thanks #Chris Heithoff)
Single quotes are handled funny by TCL, replacing them with double quotes
(that are not escaped!) resolves the issue.
The final, working command string:
exec sed -i "s/\"VALUE.${name}\">.*</\"VALUE.${name}\">${alue}</" ${dir}/impl.xml
Each argument to the exec command must correspond to an individual argument at the shell command line, so enclosing everything in {} doesn't work.
Try this:, where all double quotes and dollar signs are escaped.
exec sed -i 's/\"VALUE.\${name}\">.*</\"VALUE.\${name}\">\${value}' \${dir}/impl.xml

Delete files in a variable - bash

i have a variable of filenames that end with a vowel. I need to delete all of these files at once. I have tried using
rm "$vowels"
but that only seems to return the files within the variable and state that there is "No such file or Directory"
Its your use of quotes: they tell rm that your variables contents are to be interpreted as a single argument (filename). Without quotes the contents will be broken into multiple arguments using the shell rules in effect.
Be aware that this can be risky if your filenames contain spaces - as theres no way to tell the difference between spaces between filenames, and spaces IN filenames.
You can get around this by using an array instead and using quoted array expansion (which I cant remember the syntax of, but might look something like rm "${array[#]}" - where each element in the array will be output as a quoted string).
SOLUTION
assigning the variable
vowel=$(find . -type f | grep "[aeiou]$")
removing all files within variable
echo $vowel | xargs rm -v

How to define local variable in Buildroot which is an execution result of bash script

There's a local variable in netmap/LINUX/configure named BUILDDIR and its value is BUILDDIR=$PWD.It should have to be redirected to $(#D) which is netmap package build directory, /usr/local/buildroot/output/build/netmap-master in my case;otherwise, object files will be outputed to buildroot root directory.
I created a variable named NETMAP_CURRENT_BUILD and let it be /usr/local/buildroot/output/build/netmap-master,$(#D),
and then I wanna replace BUILDDIR=$PWD to
BUILDDIR=/usr/local/buildroot/output/build/netmap-master. By using sample code as following, it can't be done.
Sample Code :(sed part worked fine at terminal console)
define NETMAP_BUILD_CMDS
NETMAP_CURRENT_DIR = $(sed -e 's/\//\\\//g' <<< "$(#D)") -- empty
echo "$$(sed -e 's/\//\\\//g' <<< "$(#D)")" -- this line works fine
...
sed -e 's/BUILDDIR=$$PWD/BUILDDIR=$(NETMAP_CURRENT_DIR)/g' -i $(#D)/LINUX/configure
(double $$PWD, it has to be like this, which means string $PWD is needed rather than its value.)
...
endef
You don't actually need this, see below. However, if you do need the result of a shell command in a make variable, use $(shell ...)
Since this is a makefile, the $ are interpreted by make, not by the shell. Therefore, make will try to evaluate sed -e 's/\//\\\//g' <<< "$(#D)" as a variable name. There is of course no variable with that name, so you get an empty string.
To let make run a shell command and store the result in a make variable, use the $(shell ...) function. So
NETMAP_CURRENT_DIR = $(shell sed -e 's/\//\\\//g' <<< "$(#D)")
Note that that should be done outside of the NETMAP_BUILD_CMDS, because the contents of NETMAP_BUILD_CMDS is in fact a shell script: make first expands all variables in that script, then passes it to the shell line-by-line. The shell will actually error out on the above statement because you have spaces around the = so NETMAP_CURRENT_DIR is interpreted as a command name.
If you want to store the result in a shell variable rather than a make variable, then the easiest solution is to use backticks `...` to delimit the command instead of $(...):
define NETMAP_BUILD_CMDS
NETMAP_CURRENT_DIR=`sed -e 's/\//\\\//g' <<< "$(#D)"`; \
sed -e 's/BUILDDIR=$$PWD/BUILDDIR=$$NETMAP_CURRENT_DIR/g' -i $(#D)/LINUX/configure
endef
However, in your case you don't need this at all.
First of all, you can do simple substitutions directly in make.
NETMAP_CURRENT_DIR = $(subst /,\/,$(#D))
Even better, you can simply use a different delimiter than / in your sed expression, then there is no need to quote it:
sed -e 's#BUILDDIR=$$PWD#BUILDDIR=$(#D)#g' -i $(#D)/LINUX/configure
One final note: modifications to the code like this are better done in NETMAP_POST_PATCH_HOOKS than in NETMAP_BUILD_CMDS. So finally, the best solution is:
define NETMAP_FIX_BUILDDIR
sed -e 's#BUILDDIR=$$PWD#BUILDDIR=$(#D)#g' -i $(#D)/LINUX/configure
endef
NETMAP_POST_PATCH_HOOKS += NETMAP_FIX_BUILDDIR

Why does bash insert additional quotes

I need to pipe an expression including single quotes to a command, but bash inserts loads of extra quotes which breaks my command. As a really simple example take:
#!/bin/bash -x
echo 'EXPRESSION' | more
which gives:
+ echo EXPRESSION
+ more
EXPRESSION
As I want the single quotes to be displayed, I must escape them:
#!/bin/bash -x
echo \'EXPRESSION\' | more
Which now gives me:
+ echo ''\''EXPRESSION'\'''
+ more
'EXPRESSION'
So within the script, I get this bizarre ''\''EXPRESSION'\''' thing. The command I am piping the expression to is an executable that interacts with a document management system, and expects a specific format—which includes single quotes around EXPRESSION and not ''\'' and '\'''.
Is there any way to stop bash from adding the additional quotes and backslashes? I've messed around with strings and eval etc., but have failed to get rid of those additional quotes.
You can also try it with double quotes like this,
echo "'EXPRESSION'"|more
Output will be,
'EXPRESSION'
The /bin/bash -x is producing the top 2 lines. Your code produces the 3rd line. If you want you can just remove the -x and you should see it in a better way.
The above answer from Skynet works just fine, but with the -x option, it still shows 3 lines. It's just what the -x does.

Extract all variable values in a shell script

I'm debugging an old shell script; I want to check the values of all the variables used, it's a huge ugly script with approx more than 140 variables used. Is there anyway I can extract the variable names from the script and put them in a convenient pattern like:
#!/bin/sh
if [ ${BLAH} ....
.....
rm -rf ${JUNK}.....
to
echo ${BLAH}
echo ${JUNK}
...
Try running your script as follows:
bash -x ./script.bash
Or enable the setting in the script:
set -x
You can dump all interested variables in one command using:
set | grep -w -e BLAH -e JUNK
To dump all the variables to stdout use:
set
or
env
from inside your script.
You can extract a (sub)list of the variables declared in your script using grep:
grep -Po "([a-z][a-zA-Z0-9_]+)(?==\")" ./script.bash | sort -u
Disclaimer: why "sublist"?
The expression given will match string followed by an egal sign (=) and a double quote ("). So if you don't use syntax such as myvar="my-value" it won't work.
But you got the idea.
grep Options
-P --perl-regexp: Interpret PATTERN as a Perl regular expression (PCRE, see below) (experimental) ;
-o --only-matching: Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.
Pattern
I'm using a positive lookahead: (?==\") to require an egal sign followed by a double quote.
In bash, but not sh, compgen -v will list the names of all variables assigned (compare this to set, which has a great deal of output other than variable names, and thus needs to be parsed).
Thus, if you change the top of the script to #!/bin/bash, you will be able to use compgen -v to generate that list.
That said, the person who advised you use set -x did well. Consider this extension on that:
PS4=':$BASH_SOURCE:$LINENO+'; set -x
This will print the source file and line number before every command (or variable assignment) which is executed, so you will have a log not only of which variables are set, but just where in the source each one was assigned. This makes tracking down where each variable is set far easier.

Resources