How to send positional parameters to output - bash

How do I send $1,$2 etc to output in a script. I want to have a script that takes 3 arguments, a sedsrc file, a awksrc file, and a datainput file. I want the sed call to send the output to the awk. I need the awk call to take that input. Then I need the new output to be redirected into a new output file.
Ive tried
$1>temp.txt
$2>temp2.txt

You use the echo command:
echo "$1" >temp.txt
echo "$2" >temp2.txt
If you want the contents of the files named in the positional parameters, use cat:
cat "$1" >temp.txt
cat "$2" >temp2.txt

Related

Rename files reading old file name and new file name from a txt file (bash)

I need to rename a bunch of files in a directory:
2016001.fas
2016002.fas
2016003.fas
...
Reading through a .txt that has the actual and the new filename tab separated:
2016001 L.innocua001
2016002 L.innocua002
2016003 L.monocytogenes001
...
Maybe using a one line for loop or a pipe in bash.
As a note, I can also have the list with actual and new filename in .csv or comma separated .txt format if needed. I appreciate the help given.
xargs -a renames.txt -n 2 sh -c 'echo mv -- "$1.fas" "$2.fas"' _
xargs -a renames.txt: process content of the renames.txt as arguments to a command.
-n 2: pick 2 arguments at a time.
sh -c: command is to run an inline shell
The inline shell 'echo mv -- "$1.fas" "$2.fas"': Performs the actual rename using arguments 1 and 2 provided by xargs.
# remove echo when output matches the intent
echo mv -- "$1.fas" "$2.fas"
Method using a shell only to read renames.txt and execute the renames:
while read -r a b; do
# Remove echo if satisfied by the output
echo mv -- "$a.fas" "$b.fas"
done <renames.txt
Alternate method with awk to transform the renames.txt file into a shell script with the rename commands:
awk '{print "mv -- "$1".fas "$2".fas"}' renames.txt
Once satisfied by the output of awk above; save to a shell script file, or pipe directly to sh.

Adding new lines to multiple files

I need to add new lines with specific information to one or multiple files at the same time.
I tried to automate this task using the following script:
for i in /apps/data/FILE*
do
echo "nice weather 20190830 friday" >> $i
done
It does the job yet I wish I can automate it more and let the script ask me for to provide the file name and the line I want to add.
I expect the output to be like
enter file name : file01
enter line to add : IWISHIKNOW HOWTODOTHAT
Thank you everyone.
In order to read user input you can use
read user_input_file
read user_input_text
read user_input_line
You can print before the question as you like with echo -n:
echo -n "enter file name : "
read user_input_file
echo -n "enter line to add : "
read user_input_text
echo -n "enter line position : "
read user_input_line
In order to add line at the desired position you can "play" with head and tail
head -n $[$user_input_line - 1] $user_input_file > $new_file
echo $user_input_text >> $new_file
tail -n +$user_input_line $user_input_file >> $new_file
Requiring interactive input is horrible for automation. Make a command which accepts a message and a list of files to append to as command-line arguments instead.
#!/bin/sh
msg="$1"
shift
echo "$msg" | tee -a "$#"
Usage:
scriptname "today is a nice day" file1 file2 file3
The benefits for interactive use are obvious -- you get to use your shell's history mechanism and filename completion (usually bound to tab) but also it's much easier to build more complicated scripts on top of this one further on.
The design to put the message in the first command-line argument is baffling to newcomers, but allows for a very simple overall design where "the other arguments" (zero or more) are the files you want to manipulate. See how grep has this design, and sed, and many many other standard Unix commands.
You can use read statement to prompt for input,
read does make your script generic, but if you wish to automate it then you have to have an accompanying expect script to provide inputs to the read statement.
Instead you can take in arguments to the script which helps you in automation.. No prompting...
#!/usr/bin/env bash
[[ $# -ne 2 ]] && echo "print usage here" && exit 1
file=$1 && shift
con=$1
for i in `ls $file`
do
echo $con >> $i
done
To use:
./script.sh "<filename>" "<content>"
The quotes are important for the content so that the spaces in the content are considered to be part of it. For filenames use quotes so that the shell does not expand them before calling the script.
Example: ./script.sh "file*" "samdhaskdnf asdfjhasdf"

How can I log/read a string in a bash script without executing it?

I'm starting to learn how to write shell scripts. I have them all placed in a folder 'personal-scripts' in my home directory. They are starting to add up though. To solve this, I am attempting to create a script that loops over the directory and gives me a brief sentence about what each script does.
For now I can only output the script location and names via:
scriptsinfo
#!/bin/bash
for filename in ~/personal-scripts/*
do
echo $filename
done
Since I don't want to go back and update this file manually, I want to place the about sentence inside each other script either as a comment or string variable that can be evaluated.
How can I read the contents of each other script in the folder and output their string/info about what they do in this script?
You can do that using head command, which prints the first n lines of a file.
test.sh
# this is about line
# date is 14-9-2017
script data
..
..
~# head -n 2 test.sh
# this is about line
# date is 14-9-2017
If you add the description on each second line of your script, (after #!/bin/bash then let use sed -n "2p" $filenamein your script. You can also add a separator between each script:
#!/bin/bash
for filename in ~/personal-scripts/*
do
echo "---------------------"
echo $filename
echo "---------------------"
sed -n "2p" $filename
done
The alternative is to put the description anywhere, in a line starting by e.g # about: then you can grep it:
#!/bin/bash
for filename in ~/personal-scripts/*
do
echo "---------------------"
echo $filename
echo "---------------------"
grep "# about:" $filename | sed 's/# about://'
done
The | sed 's/# about://' is there to keep the description only.
If you have a comment inside all your scripts with a specific pattern such as
#info : This script runs daily
Then you can simply grep for the pattern and append to the name of the script in each line.
for filename in ~/personal-scripts/*
do
echo "$i : $(grep '#info' $i)"
done

Appending output from a command to a variable in Bash

I'm trying to append an output of a command to a variable in Bash. My code is
#!/bin/bash
for file in *
do
lineInfo=`wc -l $file`
echo "$lineInfo"
done
I understand how to "capture" the output of a command to a variable as I have done in this line by the use of backquotes.
lineInfo=`wc -l $file`
Is there a clean cut way I can place the output of that entire for loop into a variable in Bash? Or in each iteration of the for loop append the output of the wc command to linesInfo ? (Without redirecting anything to files) Thanks.
This stores all the line infos (separated by commas) into one variable and prints that variable:
#!/bin/bash
total=""
for file in *
do
lineInfo=`wc -l $file`
total="$total$lineInfo, " # or total+="$lineInfo, "
done
echo $total

How to save entire output of bash script to file

I am trying to get the entire output of a bash script to save to a file. I currently have one argument (ip address) at the beginning of the code looks like this:
#!/bin/bash
USAGE="Usage: $0 [<IP address>]"
if [ "$#" == "0" ]; then
echo "$USAGE"
exit 1
fi
ip_addr=$1
What I'd like to do is add another argument called "output", that the entire output of the script will save to. I'm aware I could just run myscript.sh | tee textfile.txt, but I'd like to make the script a little easier to run for others.
Thanks in advance,
hcaw
After the usage message, add the following line:
exec > "$2"
This will redirect standard output for the rest of the script to the file named in the 2nd argument.
Then run using
myscript 192.0.2.42 output.txt

Resources