How to save ninja build output without loosing the compressed format of output - tee

I tride to duplicate the output of the ninja build system to the separate file but I want to save original campresed look of the ninja output.
If I tee ninja (ninja all | tee -a someFile) I get wall of text enter image description here
Instead of updating one line.
If there is a better way to duplicate the output of ninja to file without loosing the compress formatig of output please let me know!
UPD: I find out that ninja update lines with [K escape sequence (erasing the line) and after capturing or rederecting ninga output it vanishing. If some body know how to allowed system to capture all tipy of escape sequence, it will solve my problem

Related

How can I add syntax highlighting to a make error message?

Summary
I want to manually add syntax highlighting of specific words in error messages. I tried with a pipeline to awk, but this doesn't seem to work with the entire message that is thrown by make. Can anybody help me to get the following pipeline working for make's entire error message?
make | awk '{for(i=1;i<=NF;i++){ if($i~/error/ || $i~/Built/) $i=sprintf("\033[0;36m %s \033[0;00m",$i)}; print}'
Or maybe—better still—a different approach to my
Situation (in detail)
To build my latex project, I use Cmake together with UseLATEX (github page). That way, I can simply render my document by executing make from inside a build folder. Only problem: There is no syntax highlighting for the wall of text of an error message. I need to add a minimal version of this, to work productively. (Maybe words could be highlighted globally in my terminal?)
By passing the output in a pipeline to awk (manpage)—inspired by this askubuntu post—I was able to highlight make's success message, pdflatex myfile.tex's success and error message, but not make's error message, it did not highlight the interesting parts of the long message.
By highlighting Built in the code snippet above, one can see that it does highlight when the first command make succeeds.
The problem is that I do not fully understand when the pipeline passes what. It seems that some output can get highlighted and some cannot.
Thanks for any help!
Steps needed to reproduce
To get into exactly the situation at hand, you need a project folder containing
build/
cmake/
myfile.tex
CMakeLists.txt
with cmake/ containing UseLATEX.cmake
and CMakeLists.txt reading
include(cmake/UseLATEX.cmake)
ADD_LATEX_DOCUMENT(myfile.tex)
and myfile.tex being a valid or non-valid latex document, e.g.
\documentclass{article}
\begin{document}
Some \undefined command
\end{document}
From inside the build/ folder, call cmake .., and then make, or rather the full command above.
The message is written on stderr, not on stdout. You have to handle stderr. In bash, you can:
make 2> >(do_something_with_stderr >&2) | do_something_with_stdout
Because | changes buffering, it's not always wanted in interactive programs. For interactive I prefer:
make 2> >(do_something_with_stderr >&2) >(do_something_with_stdout)
and sometimes that's one function:
some_func() { do_something; }
make 2> >(some_func >&2) >(some_func)

Sending script and file content via STDIN

I generate (dynamically) a script concatenating the following files:
testscript1
echo Writing File
cat > /tmp/test_file <<EOF
testcontent
line1
second line
testscript2
EOF
echo File is written
And I execute by calling
$ cat testscript1 testcontent testscript2 | ssh remote_host bash -s --
The effect is that the file /tmp/test_file is filled with the desired content.
Is there also a variant thinkable where binary files can be supplied in a similar fashion? Instead of cat of course dd could be used or other Tools, but the problem I see is 'telling' them that the STDIN now ended (can I send ^D through that stream?)
I am not able to get my head around that problem, but there is likely no comparable solution. However, I might be wrong, so I'd be happy to hear from you.
Regards,
Mazze
can I send ^D through that stream
Yes but you don't want to.
Control+D, commonly notated ^D, is just a character -- or to be pedantic (as I often am), a codepoint in the usual character code (ASCII or a superset like UTF-8) that we treat as a character. You can send that character/byte by a number of methods, most simply printf '\004', but the receiving system won't treat it as end-of-file; it will instead be stored in the destination file, just like any other data byte, followed by the subsequent data that you meant to be a new command and file etc.
^D only causes end-of-file when input from a terminal (more exactly, a 'tty' device) -- and then only in 'cooked' mode (which is why programs like vi and less can do things very different from ending a file when you type ^D). The form of ssh you used doesn't make the input a 'tty' device. ssh can make the input (and output) a 'tty' (more exactly a subclass of 'tty' called a pseudo-tty or 'pty', but that doesn't matter here) if you add the -t option (in some situations you may need to repeat it as -t -t or -tt). But then if your binary file contains any byte with the value \004 -- or several other special values -- which is quite possible, then your data will be corrupted and garbage commands executed (sometimes), which definitely won't do what you want and may damage your system.
The traditional approach to what you are trying to do, back in the 1980s and 1990s, was 'shar' (shell archive) and the usual solution to handling binary data was 'uuencode', which converts binary data into only printable characters that could go safely go through a link like this, matched by 'uudecode' which converts it back. See this surviving example from GNU. uuencode and uudecode themselves were part of a communication protocol 'uucp' used mostly for email and Usenet, which are (all) mostly obsolete and forgotten.
However, nearly all systems today contain a 'base64' program which provides equivalent (though not identical) functionality. Within a single system you can do:
base64 <infile | base64 -d >outfile
to get the same effect as cp infile outfile. In your case you can do something like:
{ echo "base64 -d <<END# >outfile"; base64 <infile; echo "END#"; otherstuff; } | ssh remote bash
You can also try:
cat testscript1 testcontent testscript2 | base64 | ssh <options> "base64 --decode | bash"
Don't worry about ^D, because when your input is exhausted, the next processes of the pipeline will notice that they have reached the end of the input file.

Add part of filename as PDF metadata using bash script and exiftool

I have about 600 books in PDF format where the filename is in the format:
AuthorForename AuthorSurname - Title (Date).pdf
For example:
Foo Z. Bar - Writing Scripts for Idiots (2017)
Bar Foo - Fun with PDFs (2016)
The metadata is unfortunately missing for pretty much all of them so when I import them into Calibre the Author field is blank.
I'm trying to write a script that will take everything that appears before the '-', removes the trailing space, and then adds it as the author in the PDF metadata using exiftool.
So far I have the following:
for i in "*.pdf";
do exiftool -author=$(echo $i | sed 's/-.*//' | sed 's/[ \t]*$//') "$i";
done
When trying to run it, however, the following is returned:
Error: File not found - Z.
Error: File not found - Bar
Error: File not found - *.pdf
0 image files updated
3 files weren't updated due to errors
What about the -author= phrase is breaking here? Please could someone enlighten me?
You don't need to script this. In fact, doing so will be much slower than letting exiftool do it by itself as you would require exiftool to startup once for every file.
Try this
exiftool -ext pdf '-author<${filename;s/\s+-.*//}' /path/to/target/directory
Breakdown:
-ext pdf process only PDF files
-author the tag to copy to
< The copy from another tag option. In this case, the filename will be treated as a pseudo-tag
${filename;s/\s+-.*//} Copying from the filename, but first performing a regex on it. In this case, looking for 1 or more spaces, a dash, and the rest of the name and removing it.
Add -r if you want to recurse into subdirectories. Add -overwrite_original to avoid making backupfiles with _original added to the filename.
The error with your first command was that the value you wanted to assign had spaces in it and needed to be enclosed by quotes.

.cat.fastq to .cat.fasta file conversion problems

I'm trying to convert fastq to fasta without doing a quality filter first. When I try to use fastx toolkit to run this conversion, it gives me an error message when it runs into a low quality base and terminates the conversion so that my converted output ends very early. (error says something like quality score below -30).
I then tried to use a sed solution posted earlier on this forum about how to convert to fasta using sed. The line was this:
sed -n '1~4s/^#/>/p;2~4p'
the line I input to the terminal was:
sed -n '1~4s/^#/>/p;2~4p' Sample_As_L001_R1.cat.fastq
It spit out what I wanted, but printed directly into the terminal.
How do I get this info to not print on the terminal, but to print to an output file?
How do I specify the file/file name that I want the output to go into. Thanks.
redirect it to a file
sed -n '1~4s/^#/>/p;2~4p' Sample_As_L001_R1.cat.fastq > Sample_As_L001_R1.cat.fasta

Stream processing lots of stuff to OVA

So one of our developers needs me to batch a bunch of information and process it into an OVA to be presented back for download. This is an easy process using the long method (ie writing to the filesystem), but the developers want a cleaner, streamlined solution that will scale better. They have therefore requested that I stream the entire processes which is proving difficult. Can someone please give me some direction. Here are the steps that need to be accomplished:
Get input from webserver (Webserver will pass these as stream eventually.)
Random password
XML file
Modify boot script on file system (ie insert random password generated by server)
Create ISO of XML file and boot script
Calculate the SHA1 sum of ISO
Append SHA1 sum of ISO to manifest file in OVF directory
Create OVA from OVF directory
Here is an example directory structure (I outlined this in / just for simplicity)
/--
|
|--ISO/
| |
| |--boot.sh (Where the random password gets inserted)
| |--config.xml (This is handed from the web server. Needs to stream from server)
|
|--OVF/
|
|--disk.vmdk
|--ovf.xml
|--manifest.mf (Contains SHA1 of all files in OVF directory)
|--boot.iso (This file will exist once created from ISO directory)
Here is what I have so far (I'll explain the issues afterwards. Yes... there are a lot of issues):
cat /ISO/boot.sh | sed "s%DEFAULT%RANDOM%" | mkisofs /ISO/* | echo "SHA1(boot.iso)= " && sha1sum >> manifest.mf | tar -cvf success.ova /OVF/*
NOTE
In boot.sh there is a variable set to DEFAULT like this (Just for testing purposes):
PASSWORD="DEFAULT"
NOTE
This is what a line in the manifest file should look like:
SHA1(boot.iso)= 5fbc0d70 BLAH BLAH BLAH a91c9121bb
So I've never tried to write an entire script in one stream before. Usually I write to the filesystem a lot as I go. The first issue I see with this is that sed is replacing the string, but what it's piping over to mkisofs will not be used as mkiosfs is just going to make an iso of what it finds in /ISO. I dont even know if you can pass something like that to mkisofs. Piping is sometimes weird to think about.
Next, I think mkisofs is ok because I didnt specify a file output, therefore it should output to stdout which will be passed to sha1sum, but and here is the next problem I see. I need to append some additional text to the file before the SHA1 sum gets added which kinda interrupts the stream.
Finally, the last problem I see is how to pass everything to be tar into OVA without writing to the filesystem first (writing to manifest.mf).
Oh and the last BIG problem which I should have mentioned first is the config.xml file. Right now im dealing with it as just a file. The dev guys want to pass it to this script as a stream as well. I dont have a clue how to handle that.
Any help would be greatly appreciated. These concepts are a little beyond my knowledge.
Thanks!
UPDATE 12/11/13 2:11PM EST
Testing each part individually right now. Will report findings below soon.
UPDATE 12/11/13 2:14PM EST
The following works:
cat /ISO/boot.sh | sed "s%DEFAULT%RANDOM%"
and produces the following output:
RANDOM="RANDOM"
Exactly as expected.
You are correct NeronLeVelu, I will have to come back later and look at sed more carefully when real random passwords are being generated. ie. Making sure proper characters are escaped. Right now though, I'm just testing the logic. I will worry about regex and escaping later. We have not even decided on random password yet. It's only temporary and will most likely be alphanumeric.
Moving onto next part. Still not sure how to take the output from sed (stdout) and use it to include in ISO creation without actually creating a file that gets written to the file system. It may not be possible without writing to file system. More to come soon
# for the password if it contain & \ and separator used in your sed (default is /)
Password4Sed="`echo \"${PASSWORD} | sed \"s/[\\/&]/\\\\&/g\"`"
# no need of a cat with a sed
sed "s/DEFAULT/${Password4Sed}/"/ISO/boot.sh > /tmp/mkisofs.input
Treat rest from this input and put some test to validate each step like empty crc value or mkisofs.input. This will help at runtime when production error occur

Resources