There really is no need for reproducing find
's output ina shell loop. If you want to pack the list of filenames, the generic formula is:
find ... | gzip > logfile.gz
If you want to gzip the files themselves, it changes to:
find ... | tar -czvf archive.tar.gz -T -
which tells tar
to read list of file names to work on from a file and the single -
stands for standard input. (The -T
AKA --files-from=
option is present in GNU tar, I'm not sure about other flavours.) Of course this breaks if you manage to work on files which contain \n
in their names.
Use
sed '/#start/,/#end/replace_command'
For example, if the file is called myconfig
,
and you want to replace "allow" with "deny" in that section, you could say
sed '/#start/,/#end/s/allow/deny/' myconfig
That would leave the file untouched, and display on the standard output
what the file would look like after the modification.
You should probably do that first,
to verify that you've got the command right.
If you want to actually change the file, add the -i
option:
sed -i '/#start/,/#end/s/allow/deny/' myconfig
If you want to replace the whole text (all the text)
between those two lines,
you can do something slightly simpler than Lucas's answer:
sed '/#start/,/#end/c\
New text line 1\
New text line 2\
︙ \
New text line n-1\
New text line n (last)' ← Close quote; no backslash here
c
is the change command in sed
(and ed
);
it means "replace entire line(s)".
You cannot simply leave the #start
and #end
lines untouched.
If you want to keep them, you must re-insert them:
sed -i '/#start/,/#end/c\
#start\
FirewallRuleSet global {\
FirewallRule allow tcp to google.com\
FirewallRule deny tcp to facebook.com\
︙ \
\
#more rules\
}\
#end' myconfig
/#start/,/#end/
specifies a range —
the lines from the first line that contains #start
through the first line after that that contains #end
.
If you need to find lines that contain those strings and nothing else,
use /^#start$/,/^#end$/
.
Best Answer
This works:
tee
saves input to a file (use-a
to append rather than overwrite), and copies the input to standard output as well.Because the command can detect that it's now being run in a non-interactive fashion this may change its behaviour. The most common side effect is that it disables colour output. If this happens (and you want ANSI colour coded output) you have to check the command documentation to see if it has a way to force it to revert to the interactive behaviour, such as
grep --color=always
. Beware that this means the log file will also include these escape codes, and you'll need to useless --RAW-CONTROL-CHARS "$log_file"
to read it without distracting escape code literals. Also beware that there is no way to make the log file contents different from what is printed to screen when running the above command, so you can't have colour coded output to screen and non-coloured output in the log file.