bubbadoobop
bubbadoobop

Reputation: 21

Testing filetypes in bash scripts and using the appropriate commands to unpack them

As of the moment I'm making a bash script that unpacks tarballs to install them. I'm on the part that unpacks the tarballs into a directoy. This is the script:

#!/Bin/bash/

# This program auto-installs tarballs for you.
# I designed this for Linux noobies who don't
# know how to install tarballs. Or, it's for
# people like me who are just lazy, and don't
# want to put in the commands ourselves.

echo "AutoTar v1.1"
echo "Gnu GPL v2.1"
read -p "Path to tarball:" pathname
cd "${pathname/#~/$HOME}"
    ls $pathname
       read -p "Please enter the file you wish to complile..." filename
if [-a $filename] == false
   then 
   echo "File does not exist! Exiting the program."
if  [[ ${filename -d} ==*.tar.gz ]]
 then
    tar -xzf $filename 
 done
else if
     [[ ${filename -d} ==*.tgz ]]
then
    tar -xzf $filename
 done
else if
   [[ ${filename -d} ==*.tar.bz2 ]]
then
    tar -xjf $filename
done
ls $pathname
echo -n "Please enter the directory of the file you have just unpacked...:"
read directory
cd $directory

What I need to do is use an if statement in order to detect the file and use the appropriate command, however I am not quite sure how to do this. With the current code I have, I simply get the error:

autotar.sh: line 18: conditional binary operator expected
autotar.sh: line 18: syntax error near `==*.tar.gz'
autotar.sh: line 18: `if  [[ ${filename -d} ==*.tar.gz ]]'

Upvotes: 0

Views: 54

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295669

If you want to check that a file doesn't exist:

if [[ ! -e $filename ]]; then ## works in bash or other ksh derivatives only

...or, for compatibility with older shells:

if [ ! -e "$filename" ]; then ## works in any POSIX shell

If you want to check for an extension:

if [[ $filename = *.tar.gz ]]; then ## works in bash or other ksh derivatives only

...or, to check for one of many extensions, consider a case statement instead:

# this works in any POSIX shell
[ -e "$filename" ] || { echo "$filename does not exist" >&2; exit 1; }

# this, too, works in any POSIX shell
case $filename in
  *.tar.gz|*.tgz)   tar -xzf "$filename" ;;
  *.tar.bz2|*.tbz2) tar -xjf "$filename" ;;
  *.tar.xz|*.txz)   xz -d <"$filename" | tar -xv ;;
  *.zip)            unzip "$filename" ;;
 esac

Note, in particular:

  • Whitespace is essential. You cannot leave out spaces. [ "$foo" = 1 ] is a valid and correct statement, whereas [$foo=1] and [ "$foo" =1] are syntax errors, and [ "$foo"==1 ] always returns true, no matter what value foo has.
  • Excepting specific exemptions, quoting expansions is mandatory for correct behavior. If you're not sure, the safe thing is to use them: You can leave out quotes in [[ ]] or case only these have special syntax rules that make them optional. If you were using [ ] instead, then you would need to use them: if [ ! -e "$filename" ].

    However, tar -xzf "$filename" or echo "$filename" or ls "$pathname" all need spaces to work correctly with interesting files or path (try names with spaces in testing your software; names with glob characters are another frequent cause of potential bugs, especially when combined).

  • [ is just a synonym for test; it's a command, not special syntax, and commands follow normal parsing rules. Just as you can't run test$foo=false, you can't run [$foo=false] or [-a $filename]; it needs to be [ -e "$filename" ] (unary use of -a is not present in the POSIX specification for test, hence the switch to -e).

Upvotes: 1

Related Questions