Inserting in line using sed command - linux

The text in file looks like this:
[homes]
comment = Home Directories
path =
browseable =
writable = yes
valid users = %S
valid users = MYDOMAIN\%S
[printers]
comment = All Printers
path = /var/spool/samba
browseable = no
guest ok = no
writable = no
printable = yes
I want output as:
[homes]
comment = Home Directories
path = /data
browseable = yes
writable = yes
valid users = %S
valid users = MYDOMAIN\%S
[printers]
comment = All Printers
path = /var/spool/samba
browseable = no
guest ok = no
writable = no
printable = yes
I am using this command:
sed -i "\#path# s#.*#& /data#" file
It makes changes to everywhere in file where path is located.
Can anyone help me with this?

sed '/path[ ]*=[ ]*$/s#$#/data#'
On lines that have path =before the endline with any amount of whitespace, replace the endline, $ with your replacement string.

Related

bash/sed - adding multiple lines at specific location in file

I want to automate adding new backends to a configuration file and can't figure out how to do it. The relevant part of the file looks like this:
[backend]
backends = backend-1 backend-2
timeout = 10
connectionsperhost = 100
[backend-1]
url = https://somedomain.com
secret = 6135bcb7849ca1886e2de193
[backend-2]
url = https://anotherdomain.com
secret = 75048ad646a5af787cbbaaa3
I'm looking for a simple solution to add another backend entry with a specific url and secret.
[backend-3]
url = https://adiffrentdomain.com
secret = 42349234238423424
and at the same time append the name "backend-3" to the line "backends = " at the "[backend]" section.
Is there a way to make this work with sed or bash scripting in genereal?
kindly appreciate any help or hints!
With awk for an arbitrary new backend entry with newbackendname, url and secret being the only provided inputs. Simply adds the new backend to the backends =-list and the corresponging block directly after the general [backend]-block.
awk -vnewentry="newbackendname" -vurl="http://new.url" -vsecret="secret123" '
#in backends= line: add new entry (at first position)
#and set `add` marker
/^backends =/{sub(/^backends = /,"&"newentry" ",$0) ; add=1}
#marker exists and empty line (end of header block) is found:
#print new entry and unset marker `add`
add && /^$/{ print "\n["newentry"]"
print "url = "url
print "secret = "secret
add=0}
#print by default
1' infile.txt
Hopefully the comments make it easy to follow. With this code, you may as well just add url and secret via shell variables as awk -vurl="$URL" -vsecret="$SECRET" -vnewentry="$NEWBACKEND" '...' infile.txt
You can try an approach with awk. It adds a backends entry to lines starting with backends and attaches a [backend-x] section with the given info after the last line of the [backend] block (after connectionsperhost).Obviously it relies on the entries of the backends being correct since it doesn't count the [backend] sections individually.
url="www.domain.com"
s=9283283h4923h42934
% awk -v url="${url}" -v s="${s}" '/^backends/{x=NF-1; $0=$0" backend-"x}
/^connectionsperhost/{ print; $0="\n[backend-"x"]\nurl = "url"\nsecret = "s}
{print}' file
[backend]
backends = backend-1 backend-2 backend-3
timeout = 10
connectionsperhost = 100
[backend-3]
url = www.domain.com
secret = 9283283h4923h42934
[backend-1]
url = https://somedomain.com
secret = 6135bcb7849ca1886e2de193
[backend-2]
url = https://anotherdomain.com
secret = 75048ad646a5af787cbbaaa3
Data
cat file
[backend]
backends = backend-1 backend-2
timeout = 10
connectionsperhost = 100
[backend-1]
url = https://somedomain.com
secret = 6135bcb7849ca1886e2de193
[backend-2]
url = https://anotherdomain.com
secret = 75048ad646a5af787cbbaaa3
Using sed
$ sed '/backends =/s/$/ backend-3/;/^\[backend-2/{N;N;s|secret.*|&\n\n[backend-3] \
url = https://adifferentdomain.com \
secret = 42349234238423424|}' input_file
[backend]
backends = backend-1 backend-2 backend-3
timeout = 10
connectionsperhost = 100
[backend-1]
url = https://somedomain.com
secret = 6135bcb7849ca1886e2de193
[backend-2]
url = https://anotherdomain.com
secret = 75048ad646a5af787cbbaaa3
[backend-3]
url = https://adiffrentdomain.com
secret = 42349234238423424
If the input is coming from variables, you would want to use double quotes instead to expand the variables. E.g;
sed "/backends =/s/$/ backend-3/;$a\\n[backend-3] \
url = $url_input \
secret = $secret_input" input_file

Unable to Access New Linux Samba Share from Windows 10

I can't connect to the Linux Samba share just created from Windows 10.
I get the "You do not have permission to access..." error message on Windows.
Any help will be appreciated. It looks like I am sooo close! FYI, I can ping, ssh into the linux box, etc. Network connectivity doesn't appear to be an issue.
Here's the smb.conf...
[global]
workgroup = SAMBA
security = user
passdb backend = tdbsam
printing = cups
log level = 2
printcap name = cups
load printers = yes
cups options = raw
hosts allow = 192.168.1.220 192.158.1.230 192.168.1.240 192.168.1.0/24
[homes]
comment = Home Directories
valid users = %S, %D%w%S
browseable = No
read only = No
inherit acls = Yes
[printers]
comment = All Printers
path = /var/tmp
printable = Yes
create mask = 0600
browseable = No
[print$]
comment = Printer Drivers
path = /var/lib/samba/drivers
write list = #printadmin root
force group = #printadmin
create mask = 0664
directory mask = 0775
[fshare]
browseable = yes
path = /home/fshare
public = yes
writeable = yes
read only = no
guest ok = yes
guest only = yes
create mode = 0777
directory mode = 0777
valid users = sambauser
In my case, I had to chmod the share folder. As root :
chmod -R 777 /home/shares/
Quite brutal, but enough for my home needs.

How to get the name of the directory from the name of the directory + the file

In an application, I can get the path to a file which resides in a directory as a string:
"/path/to/the/file.txt"
In order to write another another file into that same directory, I want to change the string "/path/to/the/file.txt" and remove the part "file.txt" to finally only get
"/path/to/the/"
as a string
I could use
string = "/path/to/the/file.txt"
string.split('/')
and then glue all the term (except the last one) together with a loop
Is there an easy way to do it?
You can use os.path.basename for getting last part of path and delete it with using replace.
import os
path = "/path/to/the/file.txt"
delete = os.path.basename(os.path.normpath(path))
print(delete) # will return file.txt
#Remove file.txt in path
path = path.replace(delete,'')
print(path)
OUTPUT :
file.txt
/path/to/the/
Let say you have an array include txt files . you can get all path like
new_path = ['file2.txt','file3.txt','file4.txt']
for get_new_path in new_path:
print(path + get_new_path)
OUTPUT :
/path/to/the/file2.txt
/path/to/the/file3.txt
/path/to/the/file4.txt
Here is what I finally used
iter = len(string.split('/'))-1
directory_path_str = ""
for i in range(0,iter):
directory_path_str = directory_path_str + srtr.split('/')[i] + "/"

Ansible append text to line in certain section of INI file

I would like to know if there is a way using Ansible to append text to the end of a line in certain section of a file, an example is going to clarify what I want to do:
Think of a file like this:
[section01]
path = /home/section01
read only = yes
list = yes
uid = apache
gid = apache
hosts deny = 0.0.0.0/0.0.0.0
hosts allow = mexico,usa,canada
[section02]
path = /home/section02
read only = yes
list = yes
uid = apache
gid = apache
hosts deny = 0.0.0.0/0.0.0.0
hosts allow = mexico,usa,canada
[section03]
path = /home/section03
read only = yes
list = yes
uid = apache
gid = apache
hosts deny = 0.0.0.0/0.0.0.0
hosts allow = mexico,usa,canada
I would like to add "brazil" on host_allow in [section02] to get this "new file"
[section01]
path = /home/section01
read only = yes
list = yes
uid = apache
gid = apache
hosts deny = 0.0.0.0/0.0.0.0
hosts allow = mexico,usa,canada
[section02]
path = /home/section02
read only = yes
list = yes
uid = apache
gid = apache
hosts deny = 0.0.0.0/0.0.0.0
hosts allow = mexico,usa,canada,brazil
[section03]
path = /home/section03
read only = yes
list = yes
uid = apache
gid = apache
hosts deny = 0.0.0.0/0.0.0.0
hosts allow = mexico,usa,canada
As #Dan Farrell mentioned in the comments, you are better off generating the entire file as partial updates can be unreliable, and problematic.
You can however use ansible templates to accomplish this as well.
You create a template file(file.ini for example) with the contents below(removed other blocks for brevity). This file would contain the full INI file contents.
[section02]
path = /home/section02
read only = yes
list = yes
uid = apache
gid = apache
hosts deny = 0.0.0.0/0.0.0.0
hosts allow = {{allow_hosts}}
Then, in your playbook, add a task to template this file.
- name: Template INI file
template:
dest: "/path/to/some/file.ini"
src: file.ini
mode: 664
owner: root
group: root
When you instantiate the playbook, you can pass the full list of allowed hosts via extra-vars.
ansible-playbook -i hosts --extra-vars="allow_hosts=mexico,usa,canada,brazil" my-playbook.yml
This however will only work for you if you know all of the allowed hosts at the time the playbook is run.

How to implement string.rfind in Lua

In Lua there's only string.find, but sometime string.rfind is needed. For example, to parse directory and file path like:
fullpath = "c:/abc/def/test.lua"
pos = string.rfind(fullpath,'/')
dir = string.sub(fullpath,pos)
How to write such string.rfind?
You can use string.match:
fullpath = "c:/abc/def/test.lua"
dir = string.match(fullpath, ".*/")
file = string.match(fullpath, ".*/(.*)")
Here in the pattern, .* is greedy, so that it will match as much as it can before it matches /
UPDATE:
As #Egor Skriptunoff points out, this is better:
dir, file = fullpath:match'(.*/)(.*)'
Yu & Egor's answer works. Another possibility using find would be to reverse the string:
pos = #s - s:reverse():find("/") + 1

Resources