I am writing a script that run other scripts. Two argument are parsing to this script. The script create a directory and copy scripts from a archive to the created folder. One of the scripts is a .config file with constants variables but I want to write the two arguments because they will be variables I will need later.
I can do with this
printf "FASTAQ1 = ${FASTA1}" >> $DIRECTORY/$FASTA1/scripts/shortcut.config
But the results is
FASTAQ1 = fasta1.fasta
But I think that what I need is this
FASTAQ1 = "fasta1.fasta"
Am I right? If so, How can I add theses quotation marks?
To print a quotation mark with printf, you can escape it with a backslash.
So, if you want to write the string FASTAQ1 = "fasta1.fasta" into a file at $DIRECTORY/$FASTA1/scripts/shortcut.config, given an environment variable FASTA1="fast1.fasta", you could do something like (ref. my bash terminal log):
FASTA1=fasta1.fasta
DIRECTORY=`pwd`
mkdir -p $DIRECTORY/$FASTA1/scripts
printf "FASTAQ1 = \"${FASTA1}\"" >> $DIRECTORY/$FASTA1/scripts/shortcut.config
Producing a shortcut.config with this contents:
FASTAQ1 = "fasta1.fasta"
Related
I am trying to convert a CMD script (.bat) into a .sh script on Linux side.
I did not find a proper documentation for instance for the following lines
set PATH="${PATH1}%;${PATH_NAME};"
another_script.bat -create "%LocalDestination%TEST;%LocalDestination%" -e %GenericEnvironementName% -d "%SettingsPath%/Env"
For the first one it is an export but I do not know it is like the if condition?
${PATH1}=${PATH_NAME}
export PATH=$PATH1
for the second one the expression
"%LocalDestination%TEST;%LocalDestination%" it's like an assignement? why we put the % at the end?
$LocalDestination$TEST = $LocalDestination
%GenericEnvironementName% will be $GenericEnvironementName
%SettingsPath%/Env >>> $SettingsPath/Env?
Variables in dos bat files are delimited with %, before AND after. So %VAR% is replaced by the value of VAR.
set PATH="${PATH1};${PATH_NAME};" assigns the values of PATH1 and PATH_NAME to variable PATH, separated by ;.
In Bash you would write: export PATH="$PATH1;$PATH_NAME"
Therefore, yes, any variable referencing is bash is done with $ before the variable name. So %TATA% becomes $TATA.
Example: %SettingsPath%/Env --> ${SettingsPath}/Env
I am trying to write a bash script that takes a variable number of file names as arguments.
The script is processing those files and creating a temporary file for each of those files.
To access the arguments in a loop I am using
for filename in $*
do
...
generate t_$(filename)
done
After the loop is done, I want to do something like cat t_$* .
But it's not working. So, if the arguments are a b c, it is catting t_a, b and c.
I want to cat the files t_a, t_b and t_c.
Is there anyway to do this without having to save the list of names in another variable?
You can use the Parameter expansion:
cat "${#/#/t_}"
/ means substitute, # means at the beginning.
How Can I access bash variables in tcl(expect) script.
I have bash file say f1.sh which set some variables like
export var1=a1
export var2=a2
These variable I need to use in my expect script .
I tried using this in my script which does not work
system "./f1.sh"
puts "var1 is $::env(var1)"
puts "var2 is $::env(var2)"
But this does not seems to work.
I see that non of the variable from f1.sh are getting set as environment variable.
system "./f1.sh" << # Is this command in my script right ?
How I need to access these bash variables from tcl file.
I would say that this problem is rather general. First I met this problem, when I wanted to initialize Microsoft Visual Studio environment (which is done using .cmd script) in PoserShell. Later I've faced this problem with other scripting languages in any combinations (Bash, Tcl, Python etc.).
Solution provided by Hai Vu is good. It works well, if you know from the beginning, which variables you need. However, if you are going to use script for initialization of some environment it my contains dozens of variables (which you don't even need to know about, but which are needed for normal operation of the environment).
In general, the solution for the problem is following:
Execute script and at the end print ALL environment variables and capture the output.
Match lines of output for the pattern like "variable=value", where is what you want to get.
Set environment variables using facilities of your language.
I do not have ready made solution, but I guess, that something similar to this should work (note, that snippets below was not tested - they are aimed only to give an idea of the solution):
Execute script; print vars and capture the output (argument expanding - {*} - requires Tcl 8.5, here we can go without it, but I prefer to use it):
set bashCommand {bash -c 'myScriptName arg1 arg2 2>&1 >/dev/null && export -p'}
if [catch {*}${bashCommand} output] {
set errMsg "ERROR: Failed to run script."
append errMsg "\n" $output
error $errMsg
}
;# If we get here, output contains the output of "export -p" command
Parse the output of the command:
set vars [dict create]
foreach line [split $output "\n"] {
regex -- {^declare -x ([[:alpha:]_]*)=\"(.*)\"$} $line dummy var val
;# 3. Store var-val pair of set env var.
}
Store var-val pair or set env var. Here several approaches can be used:
3.1. Set Tcl variables and use them like this (depending on context):
set $var $val
or
variable $var $val
3.2. Set environment variable (actually, sub-case of 3.1):
global ::env
set ::env($var) $val
3.3 Set dict or array and use it within your application (or script) without modification of global environment:
set myEnv($var) val ;# set array
dict set myEnvDict $var $val ;# set dict
I'd like to repeat, that this is only the idea of the receipt. And more important, that as most of the modern scripting languages support regexes, this receipt can provide bridge between almost arbitrary pair of languages, but not only Bash<->Tcl
You can use a here-document, like this:
#!/bin/bash
process=ssh
expect <<EOF
spawn $process
...
EOF
Exported variables are only passed from a parent process to it's children, not the other way around. The script f1.sh (actually the bash instance that's running the script) gets it's own copies of var1 and var2 and it doesn't matter if it changes them, the changes are lost when it exits. For variable exporting to work, you would need to start the expect script from the bash script.
In f1.sh, printf what you want to return...
printf '%s\n%s\n' "$var1" "$var2"
...and read it with exec in Tcl:
lassign [split [exec ./f1.sh] \n] var1 var2
Perhaps I did not look hard enough, but I don't see any way to do this. When you execute the bash script, you create a different process. What happens in that process does not propagate back to the current process.
We can work-around this issue by doing the following (thanks to potrzebie for the idea):
Duplicate the bash script to a temp script
Append to the temp script some commands at the end to echo a marker, and a list of variables and their values
Execute the temp script and parse the output
The result is a list of alternating names and values. We use this list to set the environment variables for our process.
#!/usr/bin/env tclsh
package require fileutil
# Execute a bash script and extract some environment variables
proc getBashVar {bashScript varsList} {
# Duplicate the bash script to a temp script
set tempScriptName [fileutil::tempfile getBashVar]
file copy -force $bashScript $tempScriptName
# Append a marker to the end of the script. We need this marker to
# identify where in the output to begin extracting the variables.
# After that append the list of specified varibles and their values.
set f [open $tempScriptName a]
set marker "#XXX-MARKER"
puts $f "\necho \\$marker"
foreach var $varsList {
puts $f "echo $var \\\"$$var\\\" "
}
close $f
# Execute the temp script and parse the output
set scriptOutput [exec bash $tempScriptName]
append pattern $marker {\s*(.*)}
regexp $pattern $scriptOutput all vars
# Set the environment
array set ::env $vars
# Finally, delete the temp script to clean up
file delete $tempScriptName
}
# Test
getBashVar f1.sh {var1 var2}
puts "var1 = $::env(var1)"
puts "var2 = $::env(var2)"
I have recently just made this script:
if test -s $HOME/koolaid.txt ; then
Billz=$(grep / $HOME/koolaid.txt)
echo $Billz
else
Billz=$HOME/notkoolaid
echo $Billz
fi
if test -d $Billz ; then
echo "Ok"
else touch $Billz
fi
So basically, if the file $HOME/koolaid.txt file does NOT exist, then Billz will be set as $HOME/koolaid.txt. It then sucesfully creates the file.
However, if I do make the koolaid.txt then I get this
mkdir: cannot create directory : No such file or directory
Any help would be appreciated
Here is a difference between content of a variable and evaluated content...
if your variable contains a string $HOME/some - you need expand it to get /home/login/same
One dangerous method is eval.
bin=$(grep / ~/.rm.cfg)
eval rbin=${bin:-$HOME/deleted}
echo "==$rbin=="
Don't eval unless you're absolutely sure what you evaling...
Here are a couple things to fix:
Start your script with a "shebang," such as:
#!/bin/sh
This way the shell will know that you want to run this as a Bourne shell script.
Also, your conditional at the top of the script doesn't handle the case well in which .rm.cfg exists but doesn't contain a slash character anywhere in it. In that case the rbin variable never gets set.
Finally, try adding the line
ls ~
at the top so you can see how the shell is interpreting the tilde character; that might be the problem.
How do I write a shell script (bash on HPUX) that receives a string as an argument containing an asterisk?
e.g. myscript my_db_name "SELECT * FROM table;"
The asterisk gets expanded to all the file names in the current directory, also if I assign a variable like this.
DB_QUERY="$2"
echo $DB_QUERY
The asterisk "*" is not the only character you have to watch out for, there's lots of other shell meta-charaters that can cause problems, like < > $ | ; &
The simple answer is always to put your arguments in quotes (that's the double-quote, " ) when you don't know what they might contain.
For your example, you should write:
DB_QUERY="$2"
echo "$DB_QUERY"
It starts getting awkward when you want your argument to be used as multiple parameters or you start using eval, but you can ask about that separately.
You always need to put double quotes around a variable reference if you want to prevent it from triggering filename expansion. So, in your example, use:
DB_QUERY="$2"
echo "$DB_QUERY"
In the first example, use single quotes:
myscript my_db_name 'SELECT * FROM table;'
In the second example, use double quotes:
echo "$DB_QUERY"