How can I pass a file argument to my bash script using a Terminal command in Linux?

226,622

Solution 1

It'll be easier (and more "proper", see below) if you just run your script as

myprogram /path/to/file

Then you can access the path within the script as $1 (for argument #1, similarly $2 is argument #2, etc.)

file="$1"
externalprogram "$file" [other parameters]

Or just

externalprogram "$1" [otherparameters]

If you want to extract the path from something like --file=/path/to/file, that's usually done with the getopts shell function. But that's more complicated than just referencing $1, and besides, switches like --file= are intended to be optional. I'm guessing your script requires a file name to be provided, so it doesn't make sense to pass it in an option.

Solution 2

you can use getopt to handle parameters in your bash script. there are not many explanations for getopt out there. here is an example:

#!/bin/sh

OPTIONS=$(getopt -o hf:gb -l help,file:,foo,bar -- "$@")

if [ $? -ne 0 ]; then
  echo "getopt error"
  exit 1
fi

eval set -- $OPTIONS

while true; do
  case "$1" in
    -h|--help) HELP=1 ;;
    -f|--file) FILE="$2" ; shift ;;
    -g|--foo)  FOO=1 ;;
    -b|--bar)  BAR=1 ;;
    --)        shift ; break ;;
    *)         echo "unknown option: $1" ; exit 1 ;;
  esac
  shift
done

if [ $# -ne 0 ]; then
  echo "unknown option(s): $@"
  exit 1
fi

echo "help: $HELP"
echo "file: $FILE"
echo "foo: $FOO"
echo "bar: $BAR"

see also:

links dead. here from internet archive:

Solution 3

Bash supports a concept called "Positional Parameters". These positional parameters represent arguments that are specified on the command line when a Bash script is invoked.

Positional parameters are referred to by the names $0, $1, $2 ... and so on. $0 is the name of the script itself, $1 is the first argument to the script, $2 the second, etc. $* represents all of the positional parameters, except for $0 (i.e. starting with $1).

An example:

#!/bin/bash
FILE="$1"
externalprogram "$FILE" <other-parameters>

Solution 4

Assuming you do as David Zaslavsky suggests, so that the first argument simply is the program to run (no option-parsing required), you're dealing with the question of how to pass arguments 2 and on to your external program. Here's a convenient way:

#!/bin/bash
ext_program="$1"
shift
"$ext_program" "$@"

The shift will remove the first argument, renaming the rest ($2 becomes $1, and so on).$@` refers to the arguments, as an array of words (it must be quoted!).

If you must have your --file syntax (for example, if there's a default program to run, so the user doesn't necessarily have to supply one), just replace ext_program="$1" with whatever parsing of $1 you need to do, perhaps using getopt or getopts.

If you want to roll your own, for just the one specific case, you could do something like this:

if [ "$#" -gt 0 -a "${1:0:6}" == "--file" ]; then
    ext_program="${1:7}"
else
    ext_program="default program"
fi
Share:
226,622
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    So my question is how can I pass a file argument to my bash script using a Terminal command in Linux? At the moment I'm trying to make a program in bash that can take a file argument from the Terminal and use it as a variable in my program. For example I run myprogram --file=/path/to/file in Terminal.

    My Program

    #!/bin/bash    
    File=(the path from the argument)  
    externalprogram $File (other parameters)
    

    How can I achieve this with my program?

  • Philipp
    Philipp over 13 years
    Note that all parameter expansions have to be quoted, including $file.
  • Philipp
    Philipp over 13 years
    +1 for quoting. But neither getopt nor getopts can parse GNU style arguments.
  • Admin
    Admin over 13 years
    Is there any way to implement the --file method? I want to do that because if it is run without the --file argument, the program could ask the user what file should be chosen. It will streamline the program that way.
  • Philipp
    Philipp over 13 years
    Usually you just check whether the user has supplied a file name (the parameter # contains the number of positional arguments), and use standard input if no file or - was given. If you want the --file= syntax, use a case statement.
  • Cascabel
    Cascabel over 13 years
    @Philipp: getopts can't, but getopt definitely can, on my system anyway. Presumably that comes from the fact that there's both a GNU and non-GNU version of the C function getopt.
  • Dan Moulding
    Dan Moulding over 13 years
    Yes, you're right, in this case where we expect $1 to contain a filename it should be quoted to avoid word splitting, should the filename contain one or more spaces. But is quoting positional parameters always necessary?
  • Philipp
    Philipp over 13 years
    I think it's easier to always quote all variables than to guess whether they have to be quotes. Positional arguments are user input, and users can enter anything, so unless it is documented that an argument undergoes word splitting it must be quoted. Technically, variables don't have to be quoted after = and within [[...]], but again it's easier to quote them than to remember where word splitting is not performed.
  • Dan Moulding
    Dan Moulding over 13 years
    @Philipp: Good points. Thanks!
  • David Z
    David Z over 13 years
    @Philipp (3 comments up): that does depend on how you want them interpreted. But in this case it probably makes sense - I just missed one accidentally. I'll edit it.
  • chovy
    chovy almost 11 years
    what happens when there are spaces in the file name?
  • David Z
    David Z almost 11 years
    @chovy then Bash will split it into multiple words on the spaces. For example, if the file name is test file.txt and you run externalprogram $file, the external program will see two arguments: "test" and "file.txt", but if you run externalprogram "$file", it will see one argument, "test file.txt".
  • chovy
    chovy almost 11 years
    I just needed to quote it file="$1"