Using wild cards in the arguments for a bash script - bash

I want to write a bash script which copies the last line containing a particular string from a bunch of similarly named files to a new file.
For example I have three files: 1abc1.txt, 2abc2.txt and 3abc3.txt.
From these three files i want to extract the last line containing the term "pass" and write those extracted lines to a new file named "ABC.txt".
The following is the bash script I came up with: (pass.sh)
#!/bin/bash
grepline pass "$1" 1 > $2
Then I issued the following command:
./pass.sh *abc*.txt ABC.txt
But it doesn't create the ABC.txt file. Instead it scans for the string "pass" only in 1abc1.txt and then writes the output to 2abc2.txt .
I am supposing that my use of wild cards while issuing the command is not correct. Please can anyone suggest how to achieve what I want to do with the script?

The wildcards are expanded by the shell before your script is executed, so actually you execute
./pass.sh 1abc1.txt 2abc2.txt 3abc3.txt ABC.txt
If you need to pass wildcards to your script you should quote this argument, and then let the shell expand it within the script
./pass.sh '*abc*.txt' ABC.txt
and the script should contain
grepline pass $1 1 > $2

Related

shell script to Output details of all the files in a folder passed as command line argument

So I am trying to write a script in which I will pass folder name as command line argument. The script will search a the files within that folder if it exists and output all the details. My script is as shown
for entry in "$1"/*
do
data = $(stat $entry)
echo "${data}"
done
when I run it gives me following output.
./test.sh: line 3: data: command not found
I have taken the idea from here: Stat command
Can someone help what is wrong
I have tried variations like making $entry to entry and echo $data
Your main issue is that you are putting space characters around the equal operator, you must remove them:
data=$(stat $entry)
It is also good practice to pass variables between quotes in case your folder or any of the filenames contains whitespaces:
data=$(stat "$entry")
I assume that you are storing the value into a variable because your intent is to use it into an algorithm. If you just want to call stat to list your files, you can simply call:
stat "$1"/*

How to use a csv file for multiple file inputs in command line argument of Bash Script?

Hi I am using this script named analysis.sh
#!/bin/bash
SAMPLENAME=$1;
SAVEDATA=$2;
DATAPATH=$3;
REFERENCE=$4
......
I want to give input of multiple files in CSV format instead of putting individual files details every time as to multiple files can be parsed through single script.
e.g. i have two files ABC and XYZ
so in order to analyse these two files i give these commands
For ABC
analysis.sh ABC /home/myfolder1 /home/datafolder1 /home/referncefolder1
and for XYZ
analysis.sh XYZ /home/myfolder2 /home/datafolder2 /home/referncefolder2
if i have 100 different files, how to use a single CSV file with details of these 100 files in it that can be parsed through the command line arguments of this bash script?
You can pass the name of the csv file as a single argument and have your script read it line by line:
csv=$1
while IFS=, read -r filename savedata datapath reference; do
# do the processing
done < "$csv"
See this post to understand more about how to read a text file in Bash:
Looping through the content of a file in Bash
You may want to read more about the shell variable naming convention:
Correct Bash and shell script variable capitalization

How to create one output file for each file passed to a loop in bash?

I have a file that I pass to a bash command that will create an output in a loop like so:
for file in /file/list/*
do
command
done
I wish to save the output that would have gone to standard out of each loop to a text file in my working directory. Currently I am trying this:
for file in /file/list/*
do
command | tee "$file_command output.txt"
done
What I expect to see are new files created in my current directory titled file1.txt_commandoutput.txt, file2.txt_commandoutput.txt, etc. The output of the command should be saved as a different file for each file. However I get only one file created and it's called ".txt" and can't be opened by any standard software on Mac. I am new to bash scripting, so help would be much appreciated!
Thanks.
Your problem comes from the variable name you're using:
"$file_command_output.txt" looks for a variable named file_command_output (the dot cannot be in the variable name, but the alphanumerical characters and the underscore all can).
What you're looking for is "${file}_command_output.txt" to make the variable name more explicit.
You have two issues in your script.
First, the wrong parameter/variable is expanded (file_command instead of file) because it's followed by a character that can be interpreted as part of the name (the underscore, _). To fix it, enclose the parameter name in braces, like this: ${file}_command (see Shell Parameter Expansion in bash manual).
Second, even with fixed variable name expansion, the file won't be created in your working directory, because the file holds an absolute pathname (/file/list/name). To fix it, you'll have to strip the directory from the pathname. You can do that with either basename command, or even better with a modified shell parameter expansion that will strip the longest matching prefix, like this: ${file##*/} (again, see Shell Parameter Expansion, section on ${parameter##word}).
All put together, your script now looks like:
#!/bin/bash
for file in /file/list/*
do
command | tee "${file##*/}_command output.txt"
done
Also, to just save the command output to a file, without printing it in terminal, you can use a simple redirection, instead of tee, like this: command > "${file##*/}_com...".
If you are not aware of xargs, try this:
$ ls
file
$ cat > file
one
two
three
$ while read this; do touch $this; done < ./file
$ ls
file one three two

How to save a string from a file into a variable in bash

I am trying to make a script that will ask you for a path to several files when you set it up and when you run the actual script, it reads the path from a file that you created earlier. I can make the file, I just need to know how to take that path and use it in the current script.
ex.
Settings
/home/user/launcher
Launcher
cat Settings
read PathToLaunchers
cd \$PathToLaunchers
read pathToFiles
for f in $pathToFiles
do
cat $f
done
I am just printing the contexts of each file entered in pathToFiles. You can replace cat command with the command you are interested.
If pathToFiles has only one line (i.e. only one filename), then you dnt need the for loop and just use cat $pathToFiles

Copy files to directory based on user input and using * to list files

I want to create a extremely simple bash script, my_copy.sh, that reads arbitrary number of input files, a destination directory, and finally asks for confirmation if you want to copy the files.
Example usage: ./my_copy.sh
Type in the file names to copy:
file1 file2 Anna Kurt Arne
Type in the directory to copy to:
dir_3
Are you sure you want to copy the files:
Anna
Kurt
Arne
to the directory dir_3 (y/n)?
If the destination directory does not exist, it should be created by the script.
My next question:
I want the * character to do a simple ls command. So if I type ./my_copy * , in the command line it should list all files in my directory.
Unless the * is escaped or quoted when calling your script, the shell will expand it before you script gets it.
./my_copy '*'
or
./my_copy \*
It looks like you're trying to add a simple confirmation wrapper around 'cp'. Or are you trying to make it interactively prompt the user?
You could use "cp -i", which makes it interactive and prompt before overwriting. You could also add that as an alias to .bash_profile, so it always prompts.
Your second question is quite difficult. The shell will attempt to interpret * and replace it with all items in the current directory. The only way the shell will give you a * as the only entry in the argument list is if all the files in the directory have names starting with a dot. So, your example command would actually get called with $0 = my_copy and $1 = my_copy.
You cannot give * as argument, but you can replace it with letter "e" for example and do this:
if [ "$1" = "e" ]
then
ls
else
return 0
fi

Resources