Linux add line to all files

How to append multiple lines to a file

I am writing a bash script to look for a file if it doesn’t exist then create it and append this to it:

Host localhost ForwardAgent yes 

10 Answers 10

# possibility 1: echo "line 1" >> greetings.txt echo "line 2" >> greetings.txt # possibility 2: echo "line 1 line 2" >> greetings.txt # possibility 3: cat > greetings.txt line 1 line 2 EOT # possibility 4 (more about input than output): arr=( 'line 1' 'line 2' ); printf '%s\n' "$" >> greetings.txt 

If sudo (other user privileges) is needed to write to the file, use this:

# possibility 1: echo "line 1" | sudo tee -a greetings.txt > /dev/null # possibility 3: sudo tee -a greetings.txt > /dev/null  

@ott-- You don't need a real subshell (i.e. can save one new process), this is enough: < echo "line 1" ; echo "line 2"; >>>greetings.txt

echo -e "Hello \nWorld \n" >> greetings.txt 
printf '%s\n %s\n' 'Host localhost' 'ForwardAgent yes' >> file.txt 

Or, if it's a literal tab that you want (rather than the four spaces in your question):

printf '%s\n\t%s\n' 'Host localhost' 'ForwardAgent yes' >> file.txt 

You can achieve the same effect with echo , but exactly how varies from implementation to implementation, whereas printf is consistent.

Another approach is to use tee

A few choice lines from tee 's man page:

The tee utility copies standard input to standard output, making a copy in zero or more files.

-a - Append the output to the files rather than overwriting them.

+1 tee tends to work with paths that require sudo (solutions that use > >> <

Here is an example to append multiple lines in a file:

< echo ' directory "/var/cache/bind";' echo ' listen-on < 127.0.0.1; >;' echo ' listen-on-v6 < none; >;' echo ' version "";' echo ' auth-nxdomain no;' echo ' forward only;' echo ' forwarders < 8.8.8.8; 8.8.4.4; >;' echo ' dnssec-enable no;' echo ' dnssec-validation no;' > >> your_file.txt 

It is worth to note that this variant is part of the ShellCheck recommendation github.com/koalaman/shellcheck/wiki/SC2129

SED can append a line to the end of a file like so:

sed -i '$ a text to be inserted' fileName.file
$ selects end of file, the a tells it to append, and after this comes the text that is to be inserted. Then of course the file name.

Does this approach have any added benefit than other solutions?
Yes, this approach has the added benefit of appending to any files return in a search, such as this: find . -name "*.html" -exec sed -i '$ a ' <> \;

I used the above example to insert the ending html tag that was missing on every html page within a number of directories.

Источник

Adding a line of text to multiple files

So, I have a bunch of files in a directory, and I need to insert a line of text into each of them. They have essentially the following format:

  ServerAdmin gabe@localhost DocumentRoot /var/www/test1 ServerName test1.local ServerAlias test1 Options All AllowOverride All   

tag. My first assumption is that I should be able to do this with sed, probably matching and replacing that tag. I'm going to start attempting this now, but if anyone has a existing way to do this, I'd love to hear it.

I'll be honest when I say I think this is more of a programming task. and thus should be on SO. I'd use Perl to do it, esp since I bet there's a perl module designed to parse, and modify apache configs.

Thanks, but it's a task that should be easy to accomplish with simple unix tools, hence asked here. Thanks for your comment, though.

4 Answers 4

works. If you want to repeat this command on a lot of file you can do something like:

for i in *; do sed -i 's//yourlinehere\n/' "$i"; done 

Probably better (but untested) thanks to @ChrisDown:

find . -type f -print0 | while IFS= read -r -d '' filename;\ do sed -i 's//yourlinehere\n/' $filename;\ done 

Choosing a different character than / for the sed expression is cleaner, since you don't have to escape the slash: 's::yourlinehere\n:'

If you don't mind Perl try:

perl -pi'*.old' -e 's((Your stuff here\n)' myfile 

The -i switch will save your old file with a .old extension and print to the current one.

You can also use "ex" (command-line vi) if the editing you want to do is even somewhat complicated. For example, you only want to do the insert for on one instance of "".

A shell script like this can work:

for FILENAME in *.whatever # Need a criteria to glob, or a list of names do ex -s $FILENAME / O " capital-o, not zero text to insert goes here . w! q END_EDITS done 

This approach gives you the advantages of "ex": finding a location with elaboarte patterns, and 'cursor movements'. You can do things like find a pattern, then find the next instance, THEN do the insert. Or you can change text, rather than just doing inserts. Or you can change between ranges. Don't forget that "ex" lets you use "." as the current line, so .,/^somepatter/s/blah/foo/ will work.

You can use the following single line code to insert a single line or multiple lines into a given location in a file, in you case before 'VirtualHost'. The code basically searches for the filename (it could be *.*, if you want to insert the texts in all files) within the given directory and its sub-directories. Within the files found, it searches for the pattern 'VirtualHost'. After it found the pattern, it replaces it with firstline\nsecondline\notherlines\n\VirtualHost. Note that 'VirtualHost' is part of the text for replacement, otherwise we will loss it.

find directory/ -name filename -print | xargs sed -i 's|VirtualHost|firstline\nsecondline\notherlines\nVirtualHost|g' 

You must log in to answer this question.

Hot Network Questions

Subscribe to RSS

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.7.14.43533

Linux is a registered trademark of Linus Torvalds. UNIX is a registered trademark of The Open Group.
This site is not affiliated with Linus Torvalds or The Open Group in any way.

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Источник

How can I append and prepend some text to all files in a folder in Linux

I have the folder structure like below resources/folder1 , /folder2 , /folder3 Now I want this text to be prepended with newlines:

4 Answers 4

Change directory to resources , create two template files: BEGIN and END .

File: BEGIN

File: END

Run commands:

sed -i '1s/^/\n/' */* sed -i -e '1rBEGIN' -e '$rEND' */* sed -i '1d' */* 

No backslashs escaping any more, this solution is very clear and simple and scales well.

Thanks buddy that worked. That was very easy and simple to understand. only problem is it give error when there is subdirecory as it tries to apply to that as well

Looks like a great solution but doesn't work for my case. I want to do it in the current directory and only to certain file type.

You can make that with sed :

 sed -i -e " 1s/^/\n\n\n/ ; $s/$/\n/ " $(ls -R resources/folder* ) 

There are probably a myriad ways to do it. Subject to the file names not containing spaces or the like, then you can use:

find resources -type f -print | while read file do < echo "" echo "" cat $file echo "" > > tmp.$$ cp tmp.$$ $file rm -f tmp.$$ done 

The set of braces performs I/O redirection on the enclosed commands. They're a little tricky to use accurately on the same line as commands, but the code above is easy. The redirection to tmp.$$ is OK if you are not working in a hostile environment; you might need to use mktemp or some other command if you think people might be subverting you while you run the script. The cp and rm done as shown means that you don't run into problems if any of the files is actually a symlink (or a hard link); the links are preserved. Alternatives such as mv tmp.$$ $file would break links or symlinks.

Источник

How to prepend a line to all files in a directory?

I have a directory called backup with file extensions *.sql . The thing I want to do is to prepend a line to all sql files in the directory backup . I did echo 'use my_db;' >> backup/*.sql , which didn't work. I tried the below but don't know what to do next:

ls backup/*.sql | xargs echo "use my_db;" 

3 Answers 3

for sql in backup/*.sql; do sed -i '1i\use my_db;' "$sql" done 
for sql in backup/*.sql; do sed '1i\ use my_db; ' "$sql" >"$sql.bak" && mv "$sql.bak" "$sql" done 

This would do a in-place editing of each .sql file in backup . The editing command inserts a line before the first line in each file.

This assumes that the pattern backup/*.sql only matches the files that you want to edit.

for sql in backup/*.sql; do < echo 'use my_db;'; cat "$sql"; >>"$sql.tmp" && mv "$sql.tmp" "$sql" done 

In this loop, we first output the line that we'd like to prepend to the file, then the contents of the file. This goes into a temporary file which is then renamed.

echo 'use my_db;' >> backup/*.sql 

would expand to something like

echo 'use my_db;' >> backup/file1.sql backup/file2.sql backup/file3.sql 
echo 'use my_db;' backup/file2.sql backup/file3.sql >> backup/file1.sql 

which would append the given strings to backup/file1.sql .

Your second command would not modify any files.

IIRC -i implies -s in GNU sed - so it should be possible to skip the loop and just do sed -i '1i\user mydb' backup/*.sql ( ARG_MAX notwithstanding)

Solution

sed -i '1 i\use my_db' backup/*.sql

Explanation

sed -i Keep the changes in the files, do not write them to stdout .

1 - When sed is positioned on the first line.

i - Insert the following line.

backup/*.sql Files on which sed will perform.

Will this overwrite the first line of every file? Is there a way to add to the first line moving the previous first line to the second line?

@ConnorLeech, this will insert the line use my_db as the first line and move the previously first line as the second line after insertion. If you wanted to replace/overwrite the first line, you would use c\use my_db . You can always omit the -i to see what sed does, without doing the permanent changes in file(s).

You could iterate over every file in that folder.

for item in $(ls backup/ | grep "*.sql") do echo "use my_db;" >> $item done 

Four issues: The regular expression *.sql matches a literal * . You should not parse the output of ls . The text is appended, not prepended. The variable expansion is not quoted.

What about parsing an awk output? I will face the same trouble there, even if grep is used to match sql$ as regexp, isn't it?

@Kusalananda Always better to quote, just in case, but I believe that variables used in redirections are not wordsplit, to be fair. However, Kyrie001, even if $(ls backup/ | grep "*.sql") were to work (which it won't for 5 issues it has, 3 of which are for using ls ), the intent could've been completely captured by using backup/*.sql in its place. i.e. for item in backup/*.sql

As to what those 5 issues are (provided merely to help you improve your coding): 1) ls output is not portable, for example GNU ls now does bash shell quoting by default; 2) depending on how the ls implementation outputs special characters in filenames, you'll have to parse them or they might even not be recoverable if they were all replaced with ? s; 3) the result is fed line by line and filtered by grep when filenames could consist of more than 1 line; 4) the grep regex is wrong; 5) the output of the whole pipeline is then wordsplit for the for loop.

@JoL No, the shell will not perform word splitting on the expanded value of the variable in that case, but it will perform filename globbing on the value. Having said that, any globbing would already have been performed by the loop head.

Источник

Читайте также:  Linux games racing games
Оцените статью
Adblock
detector