I have this simple set up:
pwd
/home/abc/pipetest
ls
mydir pipetest.sh
Now I do:
./pipetest.sh
And then I get
ls
file.tar.bz2 mydir pipe pipetest.sh
My question is: Why did the file named pipe get created? It contains some characters that could not be seen using vi. What's going on?
pipetest.sh contains:
#!/bin/sh
directory_name=mydir
tar cf pipe $directory_name
bzip2 -c < pipe > file.tar.bz2
tar cf pipe $directory_name writes the tar file to a file named pipe.
What you want to do is using the actual pipe:
tar c $directory_name | bzip2 > file.tar.bz2
Or simply use
tar cjf file.tar.bz2 $directory_name
tar -cf pipe
creates a tar file named "pipe" in the current directory.
Related
I can run:
echo "asdf" > testfile
tar czf a.tar.gz testfile
tar czf b.tar.gz testfile
md5sum *.tar.gz
and it turns out that a.tar.gz and b.tar.gz have different md5 hashes. It's true that they're different, which diff -u a.tar.gz b.tar.gz confirms.
What additional flags do I need to pass in to tar so that its output is consistent over time with the same input?
tar czf outfile infiles is equivalent to
tar cf - infiles | gzip > outfile
The reason the files are different is because gzip puts its input filename and modification time into the compressed file. When the input is a pipe, it uses an empty string as the filename and the current time as the modification time.
But it also has a --no-name option, which tells it not to put the name and timestamp into the file. So if you write the expanded command explicitly, instead of using the -z option to tar, you can make use of this option.
tar cf - testfile | gzip --no-name > a.tar.gz
tar cf - testfile | gzip --no-name > b.tar.gz
I tested this on OS X 10.6.8 and it works.
For MacOS:
In man tar we can look at --options section and there we will find !timestamp option, which will exclude timestamp from our gzip archive. Usage:
tar --options '!timestamp' -cvzf archive.tgz filename
It will produce same md5 sum for same files with same names
/tmp/-> ls ab*
/tmp/-> ls: ab*: No such file or directory
/tmp/-> tar -cvf ab.tar abc*
tar: abc*: Cannot stat: No such file or directory
tar: Error exit delayed from previous errors
/tmp/->
/tmp/-> ls ab*
ab.tar
/tmp/-> tar -tvf ab.tar
/tmp/->
As can be seen there are no files matching pattern abc*, however output file named ab.tar got created with no content. Is there a switch/option than can be passed to tar command so that no output file is created when there are no input file?
I’m fond of using a for-as-if construct for such cases:
for x in abc*; do
# exit the loop if no file matching abc* exists
test -e "$x" || break
# by now we know at least one exists (first loop iteration)
tar -cvf ab.tar abc*
# and since we now did the deed already… exit the “loop”
break
done
The body of the “loop” is run through exactly once, but the shell does the globbing for us. (I normally use continue in the place of the first break, but that’s probably not needed.)
Alternatively, you can use the shell to expand the glob into $*…
set -- abc*
test -e "$1" && tar -cvf ab.tar abc*
If your script runs under set -e, use if test …; then tar …; fi instead, otherwise it will abort when no file exists.
All these variants work in plain sh as well.
There is a way to get the shell to do it:
#!/bin/sh
# safetar -- execute tar safely
sh -O failglob -c 'tar cvf ab.tar abc*'
Is there a switch/option than can be passed to tar command so that no output file is created when there are no input file?
Gnu tar does not have such an option.
Here are two alternatives. You need to study them and figure out what would work for you, as they're a bit of a hack.
You could do something like:
Tar, test, remove when empty
tar -cvf ab.tar abc* ||
tar tf ab.tar | read ||
rm ab.tar
Explanation:
If tar -cvf ... fails, get the contents with tar tf ....
If the read fails, the archive was empty, and it's save to remove it.
Or you could try:
Test, then tar
ls abc* | read && tar -cvf ab.tar abc*
This would not create the empty tar file in the first place.
I have a really large tar file containing many gzip files. I would like to combine all the gzip files into one gzip file and place in another directory. To view the contents of the tar file I use:
tar -zxvf Big.tar
which gives:
Big/FileA.gz
Big/FileB.gz
Big/FileC.gz
Big/FileD.gz
To normally combine multiple gzip files I would move to that directory and use:
cat FileA.gz FileB.gz FileC.gz FileD.gz > BigFile.gz
However the BigFile.gz would remain in that directory. I'm just not sure how to do this within a tar file and how to have the combined file be written to another directory.
With GNU tar, you can do:
tar -Oxf Big.tar --wildcards 'Big/*.gz' > /tmp/your_file.gz
With OS X tar, you have to list the files individually:
tar -Oxf Big.tar Big/FileA.gz Big/FileB.gz > /tmp/your_file.gz
The salient feature in both is -O, which writes the files to stdout.
Here's an example transcript on a GNU system:
$ pwd
/home/me
$ tar tf Big.tar
Big/
Big/foo.txt.gz
Big/bar.txt.gz
$ tar -Oxf Big.tar --wildcards 'Big/*.gz' > /tmp/your_file.gz
$ zcat /tmp/your_file.gz
This is the contents of foo.txt
This is the contents of bar.txt
Using tar and assuming folder Big has FileA.gz, FileB.gz, etc.:
tar -czv -f /path/to/final/BigFile.gz -C Big .
I would like to create a .tar file from all .gz files in $a/$b and delete those files afterwards.
I have come up with the following code but it's not working:
cd "$a"
#tar cf $a/$b'.tar' "$b_sql.gz" "$b_moh.tar.gz"
tar cf $a/$b'.tar' $b'_*.gz'
gzip $a/$b'.tar'
rm -f $b'_*.gz'
I try this way and answer :
cd "$a"
for f in $b'_*.gz'
do
tar cf $a/$b'.tar' $f
done
The problem is with your use of * within a string. It's treating * as a character rather than doing the glob in the shell.
You can test this yourself by running ls *.gz and then ls '*.gz' within your shell.
I have a tar archive which contains several text files. I would like to write a script to display (stdout) the content of a file without extracting it to the current directory.
Actually I would like to do the same as:
tar tf myArchive.tar folder/someFile.txt
cat folder/someFile.txt
rm -R folder
but without the rm...
I tried this way but it didn't work:
tar tf myArchive.tar folder/someFile.txt | cat
Thanks
Use x to extract, with f from archive file. Then add also option -O to direct extracted files to standard output.
tar xf myArchive.tar folder/someFile.txt -O