3

I've sectioned off the question for easy reading, though it may be a bit stiff sounding

PROBLEM: Can't execute a bash script from what I believe to be a bash shell.

BACKGROUND: I'm trying to get started with LibGDX, and they want me to install the Android SDK as part of working in Eclipse. As such, I've got this script that's supposed to install everything that I've downloaded.

SPECS: HP Compaq dc7900 Small Form Factor Memory: 3.8 GiB Graphics: Gallium 0.4 on AMD RV620 (DRM 2.46.0 / 4.8.0-52-generic, LLVM 3.8.0)

Processor: Intel® Core™2 Duo CPU E8400 @ 3.00GHz × 2

OS: Ubuntu 16.04 64 bit

Android SDK Revision 26.0.2 (April 2017) https://developer.android.com/studio/releases/sdk-tools.html

HISTORY OF PROBLEM

Changed permissions to executable for read/write for everyone

Permissions are set as in image

Hash bang line, according to output of head command

$sudo head -1 android
#!/bin/bash

Output of checking shell

$ echo $0
/bin/bash

Opened terminal in the same folder as the target script, and tried the following commands, with the output directly below it.

$ sh android.sh
sh: 0: Can't open android.sh

$ sudo sh android.sh
[sudo] password for joel: [TYPES PASSWORD]
sh: 0: Can't open android.sh

$sh android 
android: 24: android: Syntax error: redirection unexpected

$sudo sh android
android: 24: android: Syntax error: redirection unexpected

I've also tried prefixing ~/ and ./ and they have no effect; the only pattern is that including the filename extension gives "can't open", while omitting it gives "redirection unexpected"

Interestingly, I tried opening a non existent file eirugheur.sh, and it gave the same sort of errors.

$sudo sh eirugheur.sh
sh: 0: Can't open eirugheur.sh

So I have no way of knowing whether "Can't open" means the file is missing, or if I'm goofing the commands.

Thank you for reading, any suggestions or workarounds are welcome.

EDIT: Output of ls -l

joel@joel-HP-Compaq-dc7900-Small-Form-Factor:~/Downloads/tools$ ls -l
total 1680
-rwxrwxrwx 1 joel joel   4741 May 31 15:01 android
drwxrwxr-x 2 joel joel   4096 Mar 29 00:46 bin
-rwxrw-rw- 1 joel joel 643536 Mar 29 00:46 emulator
-rwxrw-rw- 1 joel joel 394336 Mar 29 00:46 emulator-check
drwxrwxr-x 6 joel joel   4096 Mar 29 00:46 lib
-rwxrw-rw- 1 joel joel  12191 Mar 29 00:46 mksdcard
-rwxrw-rw- 1 joel joel   1257 Mar 29 00:46 monitor
-rw-rw-rw- 1 joel joel 629709 Mar 29 00:46 NOTICE.txt
drwxrwxr-x 7 joel joel   4096 Mar 29 00:46 proguard
-rw-rw-rw- 1 joel joel    139 Mar 29 00:46 source.properties
drwxrwxr-x 2 joel joel   4096 Mar 29 00:46 support
joel@joel-HP-Compaq-dc7900-Small-Form-Factor:~/Downloads/tools$

Am currently reading through steeldriver's link

EDIT: Tried steeldriver's ./android

Output:

The "android" command is deprecated.
For manual SDK, AVD, and project management, please use Android Studio.
For command-line tools, use tools/bin/sdkmanager and tools/bin/avdmanager
*************************************************************************
Invalid or unsupported command ""

Supported commands are:
android list target
android list avd
android list device
android create avd
android move avd
android delete avd
android list sdk
android update sdk

Here's the script, steeldriver's solution worked, as that error message comes from within the script. Thank you for your help, I suppose I'll get to work figuring this next one out >.>

#!/bin/bash

# Attempt to set app_home
# Resolve links: $0 may be a link
prg="$0"
# Need this for relative symlinks.
while [ -h "$prg" ] ; do
  ls=`ls -ld "$prg"`
  link=`expr "$ls" : '.*-> \(.*\)$'`
  if expr "$link" : '/.*' > /dev/null; then
    prg="$link"
  else
    prg=`dirname "$prg"`"/$link"
  fi
done
saved="`pwd`"
cd "`dirname \"$prg\"`" >/dev/null
app_home="`pwd -P`"
cd "$saved" >/dev/null

ANDROID_WRAPPER_BIN_DIR=${ANDROID_WRAPPER_BIN_DIR:-$app_home/bin}
ANDROID_WRAPPER_SDK_TIMEOUT=${ANDROID_WRAPPER_SDK_TIMEOUT:-20}

cat <<< \
"*************************************************************************
The \"android\" command is deprecated.
For manual SDK, AVD, and project management, please use Android Studio.
For command-line tools, use tools/bin/sdkmanager and tools/bin/avdmanager
*************************************************************************"

function usage {
  echo "Invalid or unsupported command \"$@\""
  echo
  echo "Supported commands are:"
  echo "android list target"
  echo "android list avd"
  echo "android list device"
  echo "android create avd"
  echo "android move avd"
  echo "android delete avd"
  echo "android list sdk"
  echo "android update sdk"
  exit 2
}

function matches {
  verbs=$1
  objects=$2
  verb=""
  object=""
  shift 2

  for arg in "$@"; do
    if [[ $arg =~ ^- ]]; then
      continue
    fi
    if [[ -z $verb && $verbs =~ ( |^)$arg( |$) ]]; then
      verb=$arg
      continue
    fi
    if [[ -n $verb && $objects =~ ( |^)$arg( |$) ]]; then
      object=$arg
      break
    fi
    break
  done
  return $([[ -n $verb && -n $object ]])
}

function echo_and_exec {
  echo "Running $@"
  echo
  exec $@
}

function parse_filter {
  local IFS=,
  for filter in $1; do
    if [[ $filter == tool || $filter == platform-tool || $filter == doc ]]; then
      command+=( "$args ${filter}s" )
    elif [[ $filter == tools || $filter == platform-tools ]]; then
      command+=( "$args ${filter}" )
    elif [[ $filter =~ ^lldb ]]; then
      command+=( "$args ${filter/-/;}" )
    elif [[ $filter =~ ^build-tools ]]; then
      command+=( "$args ${filter/build-tools-/build-tools;}" )
    elif [[ $filter == ndk ]]; then
      command+=( "$args ndk-bundle" )
    elif [[ $filter =~ ^android- ]]; then
      command+=( "$args platforms;$filter" )
    else
      echo Filter $filter not supported
      exit 2
    fi
  done
}

function confirm_try_sdk {
  for arg in "$@"; do
    if [[ $arg == --use-sdk-wrapper ]]; then
      return 0
    fi
  done
  if [[ -n $USE_SDK_WRAPPER ]]; then
    return 0
  fi
  read -t $ANDROID_WRAPPER_SDK_TIMEOUT -p "\"android\" SDK commands can be translated to sdkmanager commands on a best-effort basis.
Continue? (This prompt can be suppressed with the --use-sdk-wrapper command-line argument
or by setting the USE_SDK_WRAPPER environment variable) [y/N]: " trysdkresponse
  if (( $? > 128 )); then
    echo "Timed out waiting for input."
    echo "To suppress this prompt, run with --use-sdk-wrapper or set USE_SDK_WRAPPER."
    exit 1
  fi
  if [[ ${trysdkresponse,,} == y ]]; then
    return 0
  fi
  echo Aborted
  exit 1
}

avd_verbs="list create move delete"
avd_objects="avd target device"

if matches "$avd_verbs" "$avd_objects" "$@"; then
  echo_and_exec "$ANDROID_WRAPPER_BIN_DIR/avdmanager" "$@"
fi

sdk_verbs="list update"
sdk_objects="sdk"

if matches "$sdk_verbs" "$sdk_objects" "$@"; then
  confirm_try_sdk $@
  if [[ $verb == list ]]; then
    echo_and_exec "$ANDROID_WRAPPER_BIN_DIR/sdkmanager" --list --verbose
  fi
  if [[ $verb == update ]]; then
    command=( "$ANDROID_WRAPPER_BIN_DIR/sdkmanager" )
    prev=""
    update_all=1
    for arg in "$@"; do
      if [[ $arg == --use-sdk-wrapper || $arg == $verb || $arg == $object ]]; then
        continue
      elif [[ $arg == -n ]]; then
        echo "update sdk -n is not supported"
        exit 2
      elif [[ $arg == -s || $arg == --no-https ]]; then
        command+=("--no_https")
      elif [[ $arg == -a || $arg == --all ]]; then
        command+=("--include_obsolete")
      elif [[ $arg == -p || $arg == --obsolete || $arg == -u || $arg == --no-ui || $arg == --proxy-host ||
        $arg == --proxy-port || $arg == -t || $arg == --filter ]]; then
        :
      elif [[ $prev == --proxy-host ]]; then
        command+=("--proxy=http" "--proxy_host=$arg")
      elif [[ $prev == --proxy-port ]]; then
        command+=("--proxy_port=$arg")
      elif [[ $prev == -t || $prev == --filter ]]; then
        update_all=
        parse_filter $arg
      else
        echo Unrecognized argument $arg
        exit 2
      fi

      prev=$arg
    done
    if [[ -n $update_all ]]; then
      command+=("--update")
    fi
    echo_and_exec ${command[@]}
  fi
fi

usage $@
  • can you type ls -l then show the output (asked by somdude in a NAA post) – Bhargav Rao May 31 '17 at 20:04
  • <code>$ ls -l total 1680 -rwxrwxrwx 1 joel joel 4741 May 31 15:01 android drwxrwxr-x 2 joel joel 4096 Mar 29 00:46 bin -rwxrw-rw- 1 joel joel 643536 Mar 29 00:46 emulator -rwxrw-rw- 1 joel joel 394336 Mar 29 00:46 emulator-check drwxrwxr-x 6 joel joel 4096 Mar 29 00:46 lib -rwxrw-rw- 1 joel joel 12191 Mar 29 00:46 mksdcard -rwxrw-rw- 1 joel joel 1257 Mar 29 00:46 monitor -rw-rw-rw- 1 joel joel 629709 Mar 29 00:46 NOTICE.txt drwxrwxr-x 7 joel joel 4096 Mar 29 00:46 proguard (Omitted irrelevant lines for wordcount)</code> – Joel Nash May 31 '17 at 20:19
  • Ah, yes, that makes way more sense. – Joel Nash May 31 '17 at 20:21
0

As shown by your image, the file's name is simply android - so any attempt to run it using name android.sh will not work.

Your attempt to run it with sh is also doomed because sh is not bash. This applies regardless of the #! line or the interactive shell $0 from which you run it. (In particular, dash doesn't support things like process substitution - probably the cause of the Syntax error: redirection unexpected messages.)

The simplest way to execute it from the terminal is first to make sure the execute bit is set:

chmod +x android

and then run it using

./android

The ./ is necessary to tell the shell where to look for the file (i.e. your current directory). You could use bash android explicitly but it's better practice to let the hashbang determine which interpreter to use.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.