Working with Variables in multiple files Shell Scripts - unix

While working with Config files (user defined variables in file) I need below requirement. I have variables in config files and need to read variables from files and order of precedence. Example as
given below
Main parameter (default) file.
param.ini:
Var1=today
Var3=xyz
Override parameter file (adhoc override changes)
Param.override:
var1=yesterday
var2=123
My script as given below
test.sh:
. ~/param.override,~/param.ini
echo "run day -> $var1"
Result i need is
run day -> yesterday
I remember we can achieve this using dot operator or Source command in Unix. Please help me what will be syntax for script to call variable from multiple files.

This: works for me, not sure if you tried this?
$ cat param.ini
Var1=today
Var3=xyz
$ cat param.override
Var1=yesterday
var2=123
$ cat test.sh
#!/usr/bin/bash
. ~/cygwin/param.override ~/cygwin/param.ini
echo "run day -> $Var1"
$ ./test.sh
run day -> yesterday

Related

Issue while renaming a file with file pattern in unix

As part of our process, we get an input file in the .gz format. We need to unzip this file and add some suffix at the end of the file. The input file has timestamp so I am trying to use filter while unzipping and renaming this file.
Input file name :
Mem_Enrollment_20200515130341.dat.gz
Step 1:
Unzipping this file : (working as expected)
gzip -d Mem_Enrollment_*.dat.gz
output :
Mem_Enrollment_20200515130341.dat
Step 2: Renaming this file : (issues while renaming)
Again, I am going with the pattern but I know this won't work in this case. So, what should I do rename this file?
mv Mem_Enrollment_*.dat Mem_Enrollment_*.dat_D11
output :
Mem_Enrollment_*.dat_D11
expected output :
Mem_Enrollment_20200515130341.dat_D11
try
for fn in Mem_Enrollment_*.dat
do
mv ${fn} ${fn}_D11;
done
With just datastage you could loop over ls output from an execute command stage via "ls Mem_Enrollment_*.dat.gz" and then use an #FM as a delimiter when looping the output list. You could then breakout the gzip and rename into two separate commands, which helps with readability in your job.
Only caveat here is that the Start Loop stage doesn't accept the #FM in the delimiter due to some internal funkyness inside Datastage. So you need to set a user variable equal to it and pass that to the mark.

Initializing variables in bash

I'm migrating windows CMD script to bin/bash on unix.
The goal of initial script was to setting up some variables, so after anything run from this cmd window was using that variables.
How can I do same in UNIX? Looks like simple
MyVar="value"
doesn't work. It visible only in script itself, not from terminal where it was run.
You can initialize shell variables with simple assignments
$ foo="fooval"
$ echo $foo
fooval
These variables won't spread to unrelated child processes:
$ foo=fooval
$ sh -c 'printf "\"%s\"" $foo'
""
To make them spread, you need to export them into the process's (shell's)
environment (make them into "environment variables" (these are commonly capitalized, i.e.,
FOO instead of foo)
$ export foo
$ sh -c 'echo $foo'
fooval
You can assign and export in one step:
$ export foo=fooval
Environment variables will never spread anywhere but down the process hierarchy.
(Only to children, never to parents or completely unrelated processes)
Therefore, if you have a script with variable assignments, you need to source it, not execute it:
$ ./envvars #won't affect the parent shell
$ . ./envvars #this will
There are no per-terminal variables (though there are per-terminal configurations with fixed keys accessible manipulatable with the stty tool).
Create a file test.sh
add the following line:
export b="key"
Now goto the terminal and do the following :
source ./test.sh
echo $b
Output:
key

Combine multiple scripts in an "index.html" like fashion?

Is there a standard way in a unixesque (sh/bash/zsh) system to execute a group of scripts as if the group of scripts was one script? (Think index.html). The point is to avoid additional helper scripts like you usually find and keep small programs self sufficient and easier to maintain.
Say I have two (in bold) ruby scripts.
/bin /bin/foo_master /bin/foo_master/main
/bin/foo_master/helper.rb
So now when I execute foo_master
seo#macbook ~ $foo_master [/bin/foo_master/main]: Make
new friends, but keep the old. [/bin/foo_master/helper.rb]: One
is silver and the other gold.
If you're trying to do this without creating a helper script, the typical way to do this would just be to execute both (note: I'll use : $; to represent the shell prompt):
: $; ./main; ./helper.rb
Now, if you're trying to capture the output of both into a file, say, then you can group these into a subshell, with parenthesis, and capture the output of the subshell as if it was a single command, like so:
: $; (./main; ./helper.rb) > index.html
Is this what you're after? I'm a little unclear on what your final goal is. If you want to make this a heavily repeatable thing, then one probably would want to create a wrapper command... but if you just want to run two commands as one, you can do one of the above two options, and it should work for most cases. (Feel free to expand the question, though, if I'm missing what you're after.)
I figured out how to do this in a semi-standard complaint fashion.
I used the eval syntax in shell scripting to lambda evaluate the $PATH at runtime. So in my /etc/.zshrc
$REALPATH = $PATH
$PATH = $REALPATH:`find_paths`
where find_paths is a function that recursively searches the $PATH directories for folders (pseudocode below)
(foreach path in $PATH => ls -d -- */)
So we go from this:
seo#macbook $ echo $PATH
/bin/:/usr/bin/
To this, automagically:
seo#macbook $ echo $PATH
/bin/:/usr/bin/:/bin/foo_master/
Now I just rename main to "foo_master" and voilĂ ! Self contained executable, dare I say "app".
Yep that's an easy one!
#!/bin/bash
/bin/foo_master/main
/bin/foo_master/helper.rb
Save the file as foo_master.sh and type this in the shell:
seo#macbook ~ $sudo chmod +x foo_master.sh
Then to run type:
seo#macbook ~ $./foo_master.sh
EDIT:
The reason that an index.html file is served at any given directory is because the HTTP Server explicitly looks for one. (In server config files you can specify names of files to look for to server like index.html i.e. index.php index.htm foo.html etc). Thus it is not magical. At some point, a "helper script" is explicitly looking for files. I don't think writing a script like above is a step you can skip.

How to append a dynamic string to the end of a copy's filename

Conside File is :
/home/dev/a1234.txt
I want to copy this file in /home/sys/ directory but I want to add some number on the file name while copying.
Date1=date +%Y%m%d_%H:%M:%S
Output should be :
/home/sys/a1234.txt.$Date1
Number on the filename "1234" will be different everytime. so File name is not fixed.
Please suggest.
Something like this should get you on the way:
for i in $( ls /home/dev | grep 'a[0-9]*.txt$'); do
cp /home/dev/$i /home/sys/$i.`date +%Y%m%d_%H:%M:%S`;
done
You can improve it by seeing if the file has already been copied, and prevent it from being copied a second time.
NAME=a1234.txt
cp dev/$NAME sys/$NAME.$Date1
Use the date command to get the current date.
$ DATE=`date +%Y%m%d_%H:%M:%S`; NAME=a; EXT=txt; for i in {0..4}; do echo $NAME$i$.$EXT.$DATE; done
a0.txt.20130625
a1.txt.20130625
a2.txt.20130625
a3.txt.20130625
a4.txt.20130625
Change the echo line to be a cp:
$ DATE=`date +%Y%m%d_%H:%M:%S`; FROMDIR=/home/dev; TODIR=/home/sys; NAME=a; EXT=txt; for i in {0..4}; do cp $FROMDIR/$NAME$i.$EXT $TODIR/$NAME$i$.$EXT.$DATE; done
This is probably better in a bash script where you can modify it easier than a single liner:
#!/bin/bash
# get current date
DATE=`date +%Y%m%d_%H:%M:%S`;
# specify from directory and to directory for cp
FROMDIR=/home/dev;
TODIR=/home/sys;
# set base filename and extension
NAME=a;
EXT=txt;
# count from 0 to 4
for i in {0..4}; do
# copy file and add date to end of new filename
cp $FROMDIR/$NAME$i.$EXT $TODIR/$NAME$i$.$EXT.$DATE;
done
i increments from 0 to 4 in this example, while a filename of the form $NAME$i.$EXT is copied from $FROMDIR to TODIR -- with the current date in $DATE appended to the end of the copy's filename.
In two steps:
Copy the file to /home/sys.
cp /home/dev/a1234.txt /home/sys
Move from a1234.txt to a1234.txt.130625. This way you can make it more general.
mv /home/sys/a1234.txt{,$date} #is expanded to mv /home/sys/a1234.txt /home/sys/a1234.$date
As you indicate your file name will change, you can generalise my answer with $file_name instead of a1234.txt.
Test
$ touch a
$ date=23
$ mv aa{,$date}
$ ls
aa23

What is the usage of braces in unix commands?

I have been looking all over for how to use the {} feature in unix filenames. For example, I have a directory that has subdirectories named as an ID#. Each subdirectory has a recorded audio file named as a specific test question ID#. The following command:
for file in */1-01*; do echo "$file"; done
will list the names of the audio files within each subdirectory of the current directory. Doing so gives me a list:
809043250/1-01-20131.wav
813777079/1-01-20131.wav
817786199/1-01-20131.wav
827832538/1-01-20131.wav
834820477/1-01-20131.wav
I want to rename each of the above .wav files as a different ID#, so it should end up like this:
809043250/5001.wav
813777079/5001.wav
817786199/5001.wav
827832538/5001.wav
834820477/5001.wav
So how do I use the ${file/firstOccurance/replaceWith} notation if I want to use the mv command to keep the person's ID# (809043250, 813777079, etc) and the first / but strip off the 1-01-20131.wav and tack on 5001.wav ?
I don't know how to search for this on google. Is it called regular expressions (i don't think so...)? Brace notation? filename patterns? Does anyone know of a good explanation of these?
Thanks!
In bash, one variation on the notation is called Brace Expansion. This generates file names.
The other variation on the notation is called Shell Parameter Expansion. Here, bash provides a regex-ish substitute notation ${var/match/replace}.
For your purposes, you need the paremeter expansion:
$ x="809043250/1-01-20131.wav
> 813777079/1-01-20131.wav
> 817786199/1-01-20131.wav
> 827832538/1-01-20131.wav
> 834820477/1-01-20131.wav"
$ for file in $x; do echo $file ${file/1-01-20131/5001}; done
809043250/1-01-20131.wav 809043250/5001.wav
813777079/1-01-20131.wav 813777079/5001.wav
817786199/1-01-20131.wav 817786199/5001.wav
827832538/1-01-20131.wav 827832538/5001.wav
834820477/1-01-20131.wav 834820477/5001.wav
$

Resources