Save Bash Shell Script Output To a File with a String - linux

I have an executable that takes a file and outputs a line.
I am running a loop over a directory:
for file in $DIRECTORY/*.png
do
./eval $file >> out.txt
done
The output of executable does not contain the name of the file.
I want to append the file name with each output.
EDIT1
Perhaps, I could not explain it correctly
I want the name of the file and the output of the program as well, which is processing the same file, Now I am doing following
for file in $DIRECTORY/*.png
do
echo -n $file >> out.txt
or
printf "%s" "$file" >> out.txt
./eval $file >> out.txt
done
For both new line is inserted

If I understood your question, what you want is:
get the name of the file,
...and the output or the program processing the file (in your case, eval),
...on the same line. And this last part is your problem.
Then I'd suggest composing a single line of text (using echo), comprising:
the name of the file, this is the $file part,
...followed by a separator, you may not need that but it may help further processing of the result. I used ":". You can skip this part if this is not interesting for you,
...followed by the output of the program processing the file: this is the $(...) construct
echo $file ":" $(./eval $file) >> out.txt
...and finally appending this line of text to a file, you got that part right.

please use like this
echo -n `echo ${file}|tr -d '\n'` >> out.txt
OR
newname=`echo ${file}|tr -d '\n'`
echo -n $newname >> out.txt

Related

How to use line that read from file in grep command

I'm sorry for my poor English, first.
I want to read a file (tel.txt) that contains many tel numbers (a number per line) and use that line to grep command to search about the specific number in the source file (another file)!
I wrote this code :
dir="/home/mujan/Desktop/data/ADSL_CDR_Text_Parts_A"
file="$dir/tel.txt"
datafile="$dir/ADSL_CDR_Like_Tct4_From_960501_to_97501_Part0.txt"
while IFS= read -r line
do
current="$line"
echo `grep -F $current "$datafile" >> output.txt`
done < $file
the tel file sample :
44001547
44001478
55421487
but that code returns nothing!
when I declare 'current' variable with literals it works correctly!
what happened?!
Your grep command is redirected to write its output to a file, so you don't see it on the terminal.
Anyway, you should probably be using the much simpler and faster
grep -Ff "$file" "$datafile"
Add | tee -a output.txt if you want to save the output to a file and see it at the same time.
echo `command` is a buggy and inefficient way to write command. (echo "`command`" would merely be inefficient.) There is no reason to capture standard output into a string just so that you can echo that string to standard output.
Why don't you search for the line var directly? I've done some tests, this script works on my linux (CentOS 7.x) with bash shell:
#!/bin/bash
file="/home/mujan/Desktop/data/ADSL_CDR_Text_Parts_A/tel.txt"
while IFS= read -r line
do
echo `grep "$line" /home/mujan/Desktop/data/ADSL_CDR_Text_Parts_A/ADSL_CDR_Like_Tct4_From_960501_to_97501_Part0.tx >> output.txt`
done < $file
Give it a try... It shows nothing on the screen since you're redirecting the output to the file output.txt so the matching results are saved there.
You should use file descriptors when reading with while loop.instead use for loop to avoid false re-directions
dir="/home/mujan/Desktop/data/ADSL_CDR_Text_Parts_A"
file="$dir/tel.txt"
datafile="$dir/ADSL_CDR_Like_Tct4_From_960501_to_97501_Part0.txt"
for line in `cat $file`
do
current="$line"
echo `grep -F $current "$datafile" >> output.txt`
done

Create file with egrep matches and file names

I need some help...
I'm creating a script of unit tests using shellscripts. That script, stores all the beeline calls from all files inside a directory.
The script is doing it's purpose, but I don't wanna append the file name if grep does not return results.
That's my code:
for file in $(ls)
do
cat $file | egrep -on '^( +)?\bbeeline.*password=;"?' >> testa_scripts.sh
echo $file >> testa_scripts.sh
done
How can I do that?
Thanks
grep returns a falsy exit status (1) if it doesn't find any matching lines, so you can put in an if statement to test if it matched anything. Inverted with ! here:
for file in ./*; do
if ! egrep -on '...' "$file" >> somefile; then
echo 'grep did not match anything'
fi
done
(I don't think there's any need for the ls instead of just a shell glob here.)

What do these lines of Unix/Linux do?

I am a Unix/Linux shell script newbie and I have been asked to look at a script which contains the lines below. The following details in this question are vague but the person who wrote this code left no documentation and has since demised. Can anyone advise what they actually do?
There are two specific pieces of code. The first is simply line source polys.sh where polys.sh is a text file with contents:
failure="020o 040a"
success="002[a-d] 003[a-r] 004[a-s] 005[a-u]
Representing various parameters, I think, to do with the calculations the shell script performs. The nature of the calculations is, I am told, not important because the aim is to just get the script running.
The second piece of code is below and the relevant lines are delimited by Start and Stop comments. What I can tell you is that: $arg1 is blank, $opt1 is also blank, $poly is the path and name of a text file and ./search I believe to be a folder.
if [ $search == "yes" ]
then
# Search stage for squares containing zeros
#
# Start.
output="$outputs/search/"`basename $poly`
./search $opt1 $arg1 < $poly 2>&1 | tee $output
if tail -n1 $output | grep -v "success"
# End.
then
echo "SEARCH FAILURE" >> $output
continue
fi
# Save approximations
#
echo -n "SEARCH SUCCESS " >> $output
cat /tmp/iters >> $output
cp /tmp/zeros $inputs/search/`basename $poly`
else
echo "No search"
fi
EDIT Initial disclaimer as advised by Mr. Charles Duffy:
The below explanations assume you won't hit expansion-related bugs; please correct your code as advised by shellcheck.net to be assured that these explanations are correct
source polys.sh includes the code from the script polys.sh, which is a file in the same folder as the file sourcing it (hence just the filename, without its path).
Within that file:
failure="020o 040a"
success="002[a-d] 003[a-r] 004[a-s] 005[a-u]"
are two variable declarations; the variable $failure is set to "020o 040a" and $success to "002[a-d] 003[a-r] 004[a-s] 005[a-u]". As the file was sourced, these two variables are available in your script (do echo "$failure" and echo "$success" to see for yourself).
output="$outputs/search/`basename $poly`" has two parts to explain:
"$outputs/search/"
sets the variable $output to "$outputs/search/", i.e., to the value of the variable $outputs, appended by the string "/search/".,
`basename $poly`
anything in backticks is a command substitution, which interprets and runs the command returning its output, and the command basename $poly gets the base file or folder name from $poly, if it is a file path (e.g., basename $poly for poly="/dev/file.txt" yields file.txt); the output is appended as a string. to "$outputs/search/".
./search $opt1 $arg1 < $poly 2>&1 | tee $output is two commands, separated by a pipe |:
./search $opt1 $arg1 < $poly 2>&1
runs the executable file ./search (./ is shorthand for the current script's directory) with two arguments, $opt1 and $opt2 variables. $poly is the variable name which should represent a file path, of which the file path has its content redirected to the command (using <). The output of all errors (stderr, as 2) is redirected (>) to the standard output (stdout, or &2, the ampersand represents this is a file descriptor, not a file path, otherwise it would redirect output to a file named 2).
tee $output
tee pipes outputs stdin to stdout and to arguments as file paths. So tee "/home/nick/output" would save the stdin to a file at "/home/nick/output", as well as the stdout.
if tail -n1 $output | grep -v "success"
tail -n1 $output
gets the last line of the file at the "$output" variable's value.
grep -v "success"
searches for any non-match (-v inverts the match) in the last line from tail -n1 of "success" in a line (e.g., if the last line is "fail", it would pass the if statement as it does not contain "success")

Concatenating file names into string for a function

I'm trying to concatenate a bunch of files into a string so I can use them for a function.
As a test script I'm trying to do this:
#!/bin/bash
for line in $(cat list.txt)
do
x=" "
A=$A$line$x
done
echo "$A"
mv "$A" ./stuff
but I'm getting the error:
mv: cannot stat ‘x.dat y.dat z.dat ’: No such file or directory
but they are most definitely there
can I get some advice please?
This solution will handle file names with spaces too.
#!/bin/bash
mapfile -t lines < list.txt
echo "${lines[#]}"
mv "${lines[#]}" ./stuff/
It reads the entire contents of the file into an array variable, displays the content of the entire array, and finally uses those values in the mv command
Change the last line to mv $A ./stuff
That should work with files that do not have space in their names.

Read filenames from a text file and then make those files?

My code is given below. Echo works fine. But, the moment I redirect output of echo to touch, I get an error "no such file or directory". Why ? How do i fix it ?
If I copy paste the output of only echo, then the file is created, but not with touch.
while read line
do
#touch < echo -e "$correctFilePathAndName"
echo -e "$correctFilePathAndName"
done < $file.txt
If you have file names in each line of your input file file.txt then you don't need to do any loop. You can just do:
touch $(<file.txt)
to create all the files in one single touch command.
You need to provide the file name as argument and not via standard input. You can use command substitution via $(…) or `…`:
while read line
do
touch "$(echo -e "$correctFilePathAndName")"
done < $file.txt
Ehm, lose the echo part... and use the correct variable name.
while read line; do
touch "$line"
done < $file.txt
try :
echo -e "$correctFilePathAndName" | touch
EDIT : Sorry correct piping is :
echo -e "$correctFilePathAndName" | xargs touch
The '<' redirects via stdin whereas touch needs the filename as an argument. xargs transforms stdin in an argument for touch.

Resources