How do I pass quoted shell variables as arguments correctly? [duplicate] - linux

This question already has answers here:
Why does shell ignore quoting characters in arguments passed to it through variables? [duplicate]
(3 answers)
Variable containing multiple args with quotes in Bash
(4 answers)
Closed 10 months ago.
As part of a build pipeline I have a shell script that zips up a directory. I want to use a variable to define which patterns should be ignored.
I'm doing something like this:
IGNORE='"*.md" "some-folder/*"'
zip -x $IGNORE -r my-zip.zip ./*
Which doesn't appear to work, the ignored files and folders are still included in the zip archive.
This does work if I create the command and then pipe it through to sh though, so I'm confident that the variable contains the correct values:
echo "zip -x $IGNORE -r my-zip.zip ./*" | sh
I think it might be something to do with the quotes, since this works as expected without them. However this fails as soon as I attempt to add more than 1 pattern to IGNORE.
IGNORE=*.md
zip -x $IGNORE -r my-zip.zip ./*
What am I missing in order to be able to pass these patterns correctly quoted?
Edit: this does also not appear to work as an array, as suggested by this question.
IGNORE='"*.md" "some-folder/*"'
EXCLUDE=($IGNORE)
zip -x ${EXCLUDE[#]} -r my-zip.zip ./*

Related

How to expand variable in bash tar command [duplicate]

This question already has answers here:
bash script execute command with double quotes, single quotes and spaces
(2 answers)
Variable containing multiple args with quotes in Bash
(4 answers)
Closed 1 year ago.
I have a tar command to create .tar.gz file. It looks like below:
exclude="--exclude='.cache' --exclude='.composer' --exclude='.local' --exclude='.config'"
tar "$exclude" -czf "$backupsDir/$timestamp-home.tar.gz" /home
The problem is the $exclude variable in not evaluated and excluded directories are still in the archive. Can somebody tell me what is wrong with it? Thanks a lot.

BASH "for ... in ..." don't work with variables [duplicate]

This question already has an answer here:
In bash, how do I expand a wildcard while it's inside double quotes?
(1 answer)
Closed 2 years ago.
I want to write a simple script that does something for every file in user-defined directory. Here's a script that works for predefined directory:
for file in mydir/*; do
printf "$file"
done
Here's similar script that prints name of each file in the directory defined by variable:
for file in "$nicedir*"; do
printf "$file"
done
This second script don't work. Of course, I remembered about slash at the end of the path. (I passed ./ as the argument instead of just .)
Pathname expansion doesn't happen in quoted strings. Keep the wildcard outside of the quotes:
for file in "$nicedir"* ; do
printf '%s\n' "$file"
done
The final slash is usually not required in paths, so you'll more often see
for file in "$nicedir/"*
# or equivalent
for file in "$nicedir"/*

Writing a bash script to find all files in a directory that start with a, and do nothing if one exist [duplicate]

This question already has answers here:
Do not show results if directory is empty using Bash
(3 answers)
Closed 4 years ago.
So I have to find all the files in the directory that start with the letter a, and list them out. This is pretty easy by doing
cd some_directory
for file in a*; do
echo "$file"
done
However I want that if there are no files present that match a*, then the for loop will not run at all. Currently, if this is the case then the shell will echo
a*
Is there a way to do this? Thank you
Your text is opposite of your title, in my answer below I've assumed the text is your intention and your title is incorrect:
globs can be made to act like this with the bash shell option "nullglob":
shopt -s nullglob
An alternative is to use find and ignore errors by piping stderr to /dev/null
for file in $(find a* 2>/dev/null); do
echo "$file"
done

bash: initiate command inside of a string. - using sed [duplicate]

This question already has answers here:
How to replace a value with the output of a command in a text file?
(2 answers)
Closed 5 years ago.
my sed input is as follows:
sed 's/ListenAddress=.*/ListenAddress= $hostname/' nodemanager.properties
I am trying to run this against a Linux server and replace ListenAddress={current_value} with ListenAddress={hostname_of_server}
I need to know how to run the hostname command and have that output be reflected at the end of ListenAddress=
Thanks
If you wish your bash variables to reflect inside the sed script use, double quotes. The same is valid for command substitution. So you should be doing
sed "s/ListenAddress=.*/ListenAddress= $(hostname)/" nodemanager.properties
Since thevariable expansion takes place, you need to be careful about certain situations where $ appear as a sed attribute. For example if you're applying the above command only to the last line of the file, then do
sed "\$s/ListenAddress=.*/ListenAddress= $(hostname)/" nodemanager.properties
Note the $ before s command is escaped meaning that it is literal $ supplied to the script.

Bash script doesn't evaluate variable in filename [duplicate]

This question already has answers here:
What is the difference between ${var}, "$var", and "${var}" in the Bash shell?
(7 answers)
Closed 5 years ago.
I have a bash script which creates a backup of my folder. It should name the tar gz file using a version number but it doesn't:
#!/bin/bash
ver='1.2.3'
tar czf $ver_myfolder.tar.gz .
Expected output:
1.2.3_myfolder.tar.gz
Actual output:
_myfolder.tar.gz
If I append the variable like this:
#!/bin/bash
ver='1.2.3'
tar czf myfolder-$ver.tar.gz .
It works
You should use ${var} here since you are appending underscore after it which is considered a valid character for variable names. Due to that fact shell doesn't know whether you're expanding variable name $ver or $ver_myfolder:
ver='1.2.3'
tar czf "${ver}_myfolder.tar.gz" .
Since $ver_myfolder is unset, you get an empty value.
Because the underscore is a valid character for a variable name, you should use braces to explicitly specify the range of your variable:
${ver}_myfolder.tar.gz
^ ^
Without braces, Bash will actually try to parse
${ver_myfolder}.tar.gz
For your edited question, it is because the dot is not a valid character for a variable name, so Bash will not attempt to parse the dot into the name lookup. Even if you put it into braces, a variable name containing a dot is still invalid:
$ echo ${ver.}
bash: ${ver.}: bad substitution
$ ver.=1.2.3
ver.=1.2.3: command not found

Resources