2

My question is about Bash, Shell. I am writing a script and I have the following problem: I have a case when user declares that he or she will extract a file into a dir. But I have to test if the existence and if exist a need to check if that file is a *.tar file. I searched for similar like when checking if the file is executable:

if [ -x "file" ]; then
 echo "file is executable"
else
 echo "file is not executable"

# will this if test work?
case $1
"--extract")
 if [ -e $2 ] && [ tar -tzf $2 >/dev/null ]; then
  echo "file exists and is tar archive"
 else
  echo "file either does not exists or it is not .tar arcive"
 fi
;;
esac

Code from above doesn't work it is totally ignored. Any ideas?

jww
  • 97,681
  • 90
  • 411
  • 885
Luke_Nuke
  • 461
  • 2
  • 6
  • 23
  • 2
    Check out this: https://stackoverflow.com/questions/2001709/how-to-check-if-a-unix-tar-gz-file-is-a-valid-file-without-uncompressing – Dmitry Egorov May 07 '18 at 18:12
  • That link is good stuff. You can parse the output of `file yourfile.tar` or you could look at the extension `"${filename##*.}"` but I that top answer where you just attempt to extract the tar is the most fail-safe way of doing this. – JNevill May 07 '18 at 18:14
  • The code is missing a closing `fi`. The code should not run. Also see [How to use Shellcheck](https://github.com/koalaman/shellcheck), [How to debug a bash script?](https://unix.stackexchange.com/q/155551/56041) (U&L.SE), [How to debug a bash script?](https://stackoverflow.com/q/951336/608639) (SO), [How to debug bash script?](https://askubuntu.com/q/21136) (AskU), [Debugging Bash scripts](http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html), etc. – jww May 07 '18 at 21:35

4 Answers4

4

file command can determine file type:

file my.tar

if it is a tar file it will output:

my.tar: POSIX tar archive (GNU)

Then you can use grep to check the output (whether or not contains tar archive):

file my.tar | grep -q 'tar archive; && echo "I'm tar" || echo "I'm not tar"

In case the file does not exis, file output will be (with exit code 0):

do-not-exist.txt: cannot open `do-not-exist.txt' (No such file or directory).

You could use a case statement to handle several types of files.

Gonzalo Matheu
  • 8,984
  • 5
  • 35
  • 58
  • Thank you for your answer! However, if I am using case $1 and the user selects extract action and passes the file name as a parameter can I just $2 my.tar.gz. And If I need to check if a file exists and is tar simultaneously can I write: if [ -x $2 ] && [ $2 my.tar.gz ]; then echo "File exists and it is .tar" – Luke_Nuke May 07 '18 at 18:28
  • You should show how `file` describes a non-compressed tar file. – glenn jackman May 07 '18 at 18:28
  • This answer doesn't address tar files at all; it just identifies Gzip archives. – chepner May 07 '18 at 19:39
  • The output for tar files is '**my.tar: POSIX tar archive (GNU)**' and for non existing files is '**do-not-exist.txt: cannot open `do-not-exist.txt' (No such file or directory)**' with exit code 0. You could use a case statement to handle several cases – Gonzalo Matheu May 07 '18 at 19:55
  • Just updated the answer to use .tar files instead of .tar.gz as suggested by @chepner – Gonzalo Matheu May 07 '18 at 21:08
2

I would just see if tar can list the file:

if ! { tar ztf "$file" || tar tf "$file"; } >/dev/null 2>&1; then
    echo "$file is not a tar file"
fi
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • 1
    I'm pretty sure that the `z` option only affects the `create` operation in most modern tar implementations. When listing (`-t`) or extracting (`-x`), tar will autodetect whether decompression is required in order to read the file. (This is at least the case with GNU tar and bsdtar in FreeBSD and macOS.) – ghoti May 07 '18 at 21:09
1

I usually use a construct like this based off of the file command.

gzipped tarballs
$ file somefile1.tar.gz | grep -q 'gzip compressed data' && echo yes || echo no
yes

$ file somefile2.tar.gz | grep -q 'gzip compressed data' && echo yes || echo no
no
tarballs

The above handles gzipped tarball files, for uncompressed change out the string that grep detects:

$ file somefile1.tar | grep -q 'POSIX tar archive' && echo yes || echo no
yes

$ file somefile2.tar | grep -q 'POSIX tar archive' && echo yes || echo no
no
slm
  • 15,396
  • 12
  • 109
  • 124
0

OK, I found the answer. I know that this is not most optimal, however, it works as I intended.

I put case $1 from user into a variable and create another variable equal to *.tar.gz then in if statement I compare var1 (string from user input) with var2 equal to *tar.gz and it works.

slm
  • 15,396
  • 12
  • 109
  • 124
Luke_Nuke
  • 461
  • 2
  • 6
  • 23