How can I gzip standard in to a file and also print standard in to standard out?
echo "hey hey, we're the monkees" | tee /dev/tty | gzip --stdout > my_log.gz
As pointed out in the comments, /dev/stdout
might work better than /dev/tty
in some circumstances.
Compress files while reading data from STDIN
Yes, use gzip for this. The best way is to read data as input and redirect the compressed to output file i.e.
cat test.csv | gzip > test.csv.gz
cat test.csv
will send the data as stdout and using pipe-sign gzip will read that data as stdin. Make sure to redirect the gzip output to some file as compressed data will not be written to the terminal.
how to pipe contents of large tar.gz file to STDOUT?
Use this with GNU tar to extract a tgz to stdout:
tar -xOzf large.tar.gz --wildcards '*.html' | grep ...
-O, --to-stdout
: extract files to standard output
PostgreSQL COPY pipe output to gzip and then to STDOUT
When you use COPY ... TO PROGRAM
, the PostgreSQL server process (backend) starts a new process and pipes the file to the process's standard input. The standard output of that process is lost. It only makes sense to use COPY ... TO PROGRAM
if the called program writes the data to a file or similar.
If your goal is to compress the data that go across the network, you could use sslmode=require sslcompression=on
in your connect string to use the SSL network compression feature I built into PostgreSQL 9.2. Unfortunately this has been deprecated and most OpenSSL binaries are shipped with the feature disabled.
There is currently a native network compression patch under development, but it is questionable whether that will make v14.
Other than that, you cannot get what you want at the moment.
How do you gunzip a file and keep the .gz file?
You're looking for:
gzcat x.txt.gz >x.txt
The gzcat
command is equivalent to gunzip -c
which simply writes the output stream to stdout
. This will leave the compressed file untouched. So you can also use:
gunzip -c x.txt.gz >x.txt
Note that on some systems gzcat is also known as zcat
so run like this instead:
zcat x.txt.gz >x.txt
What standard input and output would be if there's no terminal connected to server?
The standard input and standard output (and standard error) streams can point to basically any I/O device. This is commonly a terminal, but it can also be a file, a pipe, a network socket, a printer, etc. What exactly those streams direct their I/O to is usually determined by the process that launches your process, be that a shell or a daemon like cron or apache, but a process can redirect those streams itself it it would like.
I'll use Linux as an example, but the concepts are similar on most other OSes. On Linux, the standard input and standard output stream are represented by file descriptors 0
and 1
. The macros STDIN_FILENO
and STDOUT_FILENO
are just for convenience and clarity. A file descriptor is just a number that matches up to some file description that the OS kernel maintains that tells it how to write to that device. That means that from a user-space process's perspective, you write to pretty much anything the same way: write(some_file_descriptor, some_string, some_string_length)
(higher-level I/O functions like printf
or cout
are just wrappers around one or more calls to write
). To the process, it doesn't matter what type of device some_file_descriptor
represents. The OS kernel will figure that out for you and pass your data to the appropriate device driver.
The standard way to launch a new process is to call fork
to duplicate the parent process, and then later to call one of the exec
family of functions in the child process to start executing some new program. In between, it will often close the standard streams it inherited from its parent and open new ones to redirect the child process's output somewhere new. For instance, to have the child pipe its output back to the parent, you could do something like this in C++:
int main()
{
// create a pipe for the child process to use for its
// standard output stream
int pipefds[2];
pipe(pipefds);
// spawn a child process that's a copy of this process
pid_t pid = fork();
if (pid == 0)
{
// we're now in the child process
// we won't be reading from this pipe, so close its read end
close(pipefds[0]);
// we won't be reading anything
close(STDIN_FILENO);
// close the stdout stream we inherited from our parent
close(STDOUT_FILENO);
// make stdout's file descriptor refer to the write end of our pipe
dup2(pipefds[1], STDOUT_FILENO);
// we don't need the old file descriptor anymore.
// stdout points to this pipe now
close(pipefds[1]);
// replace this process's code with another program
execlp("ls", "ls", nullptr);
} else {
// we're still in the parent process
// we won't be writing to this pipe, so close its write end
close(pipefds[1]);
// now we can read from the pipe that the
// child is using for its standard output stream
std::string read_from_child;
ssize_t count;
constexpr size_t BUF_SIZE = 100;
char buf[BUF_SIZE];
while((count = read(pipefds[0], buf, BUF_SIZE)) > 0) {
std::cout << "Read " << count << " bytes from child process\n";
read_from_child.append(buf, count);
}
std::cout << "Read output from child:\n" << read_from_child << '\n';
return EXIT_SUCCESS;
}
}
Note: I've omitted error handling for clarity
This example creates a child process and redirects its output to a pipe. The program run in the child process (ls
) can treat the standard output stream just as it would if it were referencing a terminal (though ls
changes some behaviors if it detects its standard output isn't a terminal).
This sort of redirection can also be done from a terminal. When you run a command you can use the redirection operators to tell your shell to redirect that commands standard streams to some other location than the terminal. For instance, here's a convoluted way to copy a file from one machine to another using an sh-like shell:
gzip < some_file | ssh some_server 'zcat > some_file'
This does the following:
- create a pipe
- run
gzip
redirecting its standard input stream to read from "some_file" and redirecting its standard output stream to write to the pipe - run
ssh
and redirect its standard input stream to read from the pipe - on the server, run
zcat
with its standard input redirected from the data read from the ssh connection and its standard output redirected to write to "some_file"
Can you use gzip to just compress text that you type into the terminal?
Yes, you can, but it's not a common thing to do.
For example, this is perfectly legal (I typed "Hello, world.
", then Enter, then Ctrl-D).
$ gzip > input.gz
Hello, world.
$ ls -l input.gz
-rw-r--r-- 1 kst kst 34 Oct 5 23:18 input.gz
$ gzip -d < input.gz
Hello, world.
(The compressed file is actually bigger than the input; this is common for very small inputs.)
But remember that standard input doesn't have to come from the keyboard. For example, the du
command prints a summary of disk usage, and can generate a lot of output if you run it on a large directory. If you want to save the output directly in compressed form, you might type:
du -a / | gzip > du-a.out.gz
The standard input of the gzip
command comes from the output of the du -a /
command; its standard output is written to the new file du-a.out.gz
.
The tar
command is another common example:
tar cf - some_dir | gzip > some_dir.tar.gz
(but many versions of tar
have options to do this without having to explicitly invoke the gzip
command).
As for the last part of your question:
Also, when I type gzip -f in my terminal, cursor goes to newline and starts accepting input but I just have to Ctrl+C it out and then nothing happens.
Typing Ctrl-C kills the gzip
process, and may not allow it to finish writing its output. You need to type Ctrl-D to trigger an end-of-file condition; this lets the gzip -f
command finish normally. But you don't generally want to do that; it will write the compressed output to your terminal, which can include control characters that can mess up your terminal settings.
Perl to parse text file which may or may not be gzipped
open $FILE, "zcat -f $file|" or die $!;
man zcat
-f --force
If the input data is not in a format recognized by gzip, and if the option --stdout is also given, copy the input data without change to the standard output: let zcat behave as cat.
Zip file and print to stdout
The zip
program from Info-ZIP (the one usually found on Linux systems) allows generating ZIP files into the standard output, when you use -
as the name of the file. For example you could send a zip file to port 8787 on a remote host with this command:
zip -r - files_to_be_archived | nc remotehost 8787
All of this is documented on the zip command manual page.
Related Topics
How to Diff Top Lines of Two Files Without Intermediate File
Hook into Linux Key Event Handling
How to Use Awk for a Compressed File
How to Check Whether the Processor Cache Has Been Flushed Recently
How to Disable Editing My History in Bash
Checkpoint/Restart Using Core Dump in Linux
How to Flush Cache of Hard-Disk and Flash-Disk (Or Filesystem) from Command Line
How to Make a Bash Script Portable Between Linux and Freebsd
Must a Process Group Have a Running Leader Process
Pass Private Key Password to Openvpn Command Directly in Ubuntu 10.10
Injecting Code into Executable at Runtime
What Tools Do I Need to Develop in Actionscript (In Linux)
Shell Script Change Directory with Variable
Run Silverlight with Apache Server (Under Linux)
How to Add a String to the Beginning of Each File in a Folder in Bash
Accessing Linux /Dev/Usb as Standard Files to Communicate with Usb Device