Here is a simple example showing that using declare in a script the script will not run, while sourcing the script will:

$ cat /tmp/new
#! /bin/sh
declare -i  hello
$ chmod a+rwx /tmp/new
$ /tmp/new
/tmp/new: 3: declare: not found
$ source /tmp/new

I wonder why directly running the script doesn't work, while sourcing it does? How can I make the first one work? Thanks!

4 Answers 4


declare is a builtin function and it's not available with /bin/sh, only with bash or zsh (and maybe other shells). The syntax may differ from one shell to another. You must choose your sheebang (#!) accordingly: if the script needs to be run by bash, the first line must be



#!/usr/bin/env bash

declare is a bash and zsh extension. On your system, /bin/sh is neither bash nor zsh (it's probably ash), so declare isn't available. You can use typeset instead of declare; they're synonyms, but typeset also works in ksh. In ash, there's no equivalent to typeset -i or most other uses of the typeset built-in. You don't actually need typeset -i to declare an integer variable; all it does is allow a few syntactic shortcuts like hello=2+2 for hello=$((2+2)).


declare probably doesn't exist in the shell defined by your shebang - #! /bin/sh.

Try #!/bin/bash instead.

The reason why sourcing it worked is that you were already in a shell that supports declare. Sourcing it didn't open a new shell thus didn't use the shebang that doesn't know declare.


You may also try the 2 other equivalent versions to Bash's declare, which are: typeset and local. They all work with -i (for integer). Also see my test script. PS. declare is not yet implemented in the Android (Mksh).

  • local works fine
    – Quanlong
    Jan 11, 2018 at 10:26
  • typeset will work for ksh Jan 21, 2022 at 18:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .