How to insert variable into file at a specified position - bash

I'm building a script that will search for all the files in a certain directory.
Then I put the files that it found in the file files.txt, like below:
ls /opt/files/ | while read line
do
files=`echo $line | grep -o '[^ ]*$'`
echo $files >> files.txt
done
Now I want to put the found file in an other file called config.properties at a specified position.
Below you will see how the config.properties file looks like.
rest.server.url=https\://hostname/RestService/
rest.username=user
rest.password=pass
rest.response.type=json
hotfix.async=false
hotfix.operation=hotfix
hotfix.dlFilePath=/opt/files/<file>
So at the I want to insert the filename that has been found.
I came up with the following code below:
cat files.txt | while read files
do
#How can I code the part below?
insert $files into config.properties at line hotfix.dlFilePath=/opt/files/<file>
done
Only how can I insert $files in the config.properties file at the position of ?
I have a feeling it can be done with awk or sed, but not sure.

Perhaps try and integrate this solution using sed:
sed -i -E "s/(^hotfix\.dlFilePath\=\/opt\/files\/)(.*$)?/\1$files/" config.properties
Please note the use of double quotes around the substitution expression in sed to make the shell expand variables. So, with a variable like this
files="foo"
and given this input (assuming that the <file> was just a placeholder):
rest.server.url=https\://hostname/RestService/
rest.username=user
rest.password=pass
rest.response.type=json
hotfix.async=false
hotfix.operation=hotfix
hotfix.dlFilePath=/opt/files/
you'll get this result
rest.server.url=https\://hostname/RestService/
rest.username=user
rest.password=pass
rest.response.type=json
hotfix.async=false
hotfix.operation=hotfix
hotfix.dlFilePath=/opt/files/foo

Are you saying that you want to generate the file config.properties so that it has one stanza for each file that you find? Just do:
for file in /opt/files/*; do
cat << EOF
rest.server.url=https\://hostname/RestService/
rest.username=user
rest.password=pass
rest.response.type=json
hotfix.async=false
hotfix.operation=hotfix
hotfix.dlFilePath=$file
EOF
done > config.properties

Related

Bash: Delete a line from a file matching a variable

I have four files named source, correct, wrong and not_found. I am trying to write a script in bash wherein I read each line from file named source, store the line as variable x, and match it against a condition.
If it passes, then I need to write that line to file named correct, but the catch is before writing into correct I need to check if the variable x is currently present in file named wrong and if yes delete it and then add the line to file named correct.
I have tried below, but it doesn't modify the file and neither gives me any output:
sed -i '/$x/d' ./wrong
As you have already understood, variables inside '...' are not expanded.
If you replace the single-quotes with double-quotes,
this will delete the matching line from ./wrong:
sed -i "/$x/d" ./wrong
But you also want to add the line to ./correct, if there was a match.
To do that, you can run grep before the sed:
grep "$x" ./wrong >> ./correct
This will have the desired effect,
but sed will overwrite ./wrong, even when it doesn't need to.
You can prevent that like this:
if grep "$x" ./wrong >> ./correct; then
sed -i "/$x/d" ./wrong
fi

How to read all text file with head linux command?

I can't read or apply any other commands like cat or strings on .txt files because it is not allowed. I need to read a file named flag.txt, but this file is also on the blacklist. So, is there any way to read *.txt using the head command? The head command is allowed.
blacklist=\
'flag\|<\|$\|"\|'"'"'\|'\
'cat\|tac\|*\|?\|less\|more\|pico\|nano\|edit\|hexdump\|xxd\|'\
'sed\|tail\|diff\|grep\|paste\|strings\|bas64\|sort\|uniq\|cut\|awk\|'\
'bzip\|gzip\|xz\|tar\|ar\|'\
'mv\|cp\|ln\|nl\|'\
'python\|perl\|sh\|cc\|g++\|php\|hd\|g++\|gcc\|curl\|tcp\|udp\|'\
'scp\|sftp\|wget\|nc\|netcat'
Thanks
do you want some alternative of the command head *.txt? if so, ls/findand xargs will help, but it can not identify .txt file, it will read all the file under the directory.
ls -1| xargs head
You can use the ` (backtick) in the following way:
head `ls -1`
Backtick has a very special meaning. Everything you type between
backticks is evaluated (executed) by the shell before the main command
So the command will do the following:
`ls -1` - will result with the file names
head - will show the start of the files listed in ls -1
More info about backtick can be found in this answer
If you need a glob that matches flag.txt but can use neither * not the string flag, you can use fl[a]g.txt instead. Then, to print the entire file using head, use -c and pass it the size of the file:
head -c $(stat -c '%s' fl[a]g.txt) fl[a]g.txt
Another approach would be to use the shell to read the file:
while IFS= read -r c; do echo $c; done < fl[a]g.txt
You could also just use paste:
paste fl[a]g.txt

Bash script to replace info in file

I have a new file that I created that has a list of all directories that have a particular file:
$ find . -name "bun.biscuts" > TREE.temp
This writes all of the correct info I need to the new temp file.
I am having trouble writing a bash script using sed to replace emails in the TREE.temp file.
This is what I have so far:
#!/bin/bash
#set -x
echo Start!
for bun.biscuts in (TREE.temp)
do
sed -i 's/EMAIL1/EMAIL2/g';
done
Any help would be amazing!
gniourf_gniourf's comment is right; you don't need to use a temporary file and loop to do this. But if you want to, you could do it like this:
while read; do
sed -i 's/EMAIL1/EMAIL2/g' "$REPLY"
done < TREE.temp
which performs the sed operation on the filename on each line of the file. $REPLY is the default variable name that each line is written to by read. You can change the variable name by doing read var instead - then each line will be written to $var.
You can use only one sed command:
sed -i.bak 's/EMAIL1/EMAIL2/g' TREE.temp
If you have node on the computer you can npm install -g rexreplace and then
rexreplace 'email1' 'email2' TREE.tmp

How to copy multiple files and rename them at once by appending a string in between the file names in Unix?

I have a few files that I want to copy and rename with the new file names generated by adding a fixed string to each of them.
E.g:
ls -ltr | tail -3
games.txt
files.sh
system.pl
Output should be:
games_my.txt
files_my.sh
system_my.pl
I am able to append at the end of file names but not before *.txt.
for i in `ls -ltr | tail -10`; do cp $i `echo $i\_my`;done
I am thinking if I am able to save the extension of each file by a simple cut as follows,
ext=cut -d'.' -f2
then I can append the same in the above for loop.
do cp $i `echo $i$ext\_my`;done
How do I achieve this?
You can use the following:
for file in *
do
name="${file%.*}"
extension="${file##*.}"
cp $file ${name}_my${extension}
done
Note that ${file%.*} returns the file name without extension, so that from hello.txt you get hello. By doing ${file%.*}_my.txt you then get from hello.txt -> hello_my.txt.
Regarding the extension, extension="${file##*.}" gets it. It is based on the question Extract filename and extension in bash.
If the shell variable expansion mechanisms provided by fedorqui's answer look too unreadable to you, you also can use the unix tool basename with a second argument to strip off the suffix:
for file in *.txt
do
cp -i "$file" "$(basename "$file" .txt)_my.txt"
done
Btw, in such cases I always propose to apply the -i option for cp to prevent any unwanted overwrites due to typing errors or similar.
It's also possible to use a direct replacement with shell methods:
cp -i "$file" "${file/.txt/_my.txt}"
The ways are numerous :)

Insert content into template file using bash

I have a template file I want to copy and then edit from a script, inserting content at specific template points. For example, my template file might be something like,
...
rm -rf SomeDirectory
make install
#{INSERT-CONTENT-HERE}
do-something-else
...
In another script, I want to add content at "#{INSERT-CONTENT-HERE}" within a loop, i.e.
for i in c; do
# Write content to the template file copy at the correct point.
done
I think sed is the right tool, but I'm not familiar enough to know the syntax, and the man page isn't helping.
An example:
echo "Line #{INSERT-CONTENT-HERE}" | sed 's/#{INSERT-CONTENT-HERE}/---/'
To modify a file:
sed -i 's/#{INSERT-CONTENT-HERE}/---#{INSERT-CONTENT-HERE}/' filename
where -i means in-place edit so be warned
if you do:
sed -i.bak 's/#{INSERT-CONTENT-HERE}/---/' filename
it should back up original as filename.bak
also to make multiple substitutions at each line use the g flag:
sed -i.bak 's/#{INSERT-CONTENT-HERE}/---/g' filename
You can copy the output of all the commands into a temporary file and then copy the contents of that entire file into the template file:
TEMPFILE=`mktemp` && (
for i in c
echo "SomeTextBasedOn $i" >> $TEMPFILE
done
sed -i '/{INSERT-CONTENT-HERE}/r '$TEMPFILE targetfile
rm $TEMPFILE
)

Resources