How to handle "-" in script shell arguments?

This question has three parts, and each of them is simple, but together they are not trivial (at least for me) :)

You need to write a script, which should take as arguments:

  • one name of another team
  • some arguments for the team
  • list of files

Examples:

./my_script head -100 a.txt b.txt ./xxx/*.txt
./my_script sed -n 's/xxx/aaa/' *.txt

etc.

Inside my script for some reason I need to distinguish

  • which team
  • what are the arguments for the team
  • what files

therefore, probably the most standard way to write the above examples:

./my_script head -100 -- a.txt b.txt ./xxx/*.txt
./my_script sed -n 's/xxx/aaa/' -- *.txt

Question1: Is this the best solution?

Processing c. / my _script (first try):

command="$1";shift
args=`echo $* | sed 's/--.*//'`
filenames=`echo $* | sed 's/.*--//'`

#... some additional processing ...

"$command" "$args" $filenames #execute the command with args and files

This solution will fail if filenamesit contains spacesand / or '-', for example,
/ some - path / to / more / idiotic file name.txt

Question2: $command $args $filenames ?

Question3: - ?

echo $filenames | $command $args #but want one filename = one line (like ls -1)

, , perl?

+5
3

, , script, . bash:

$ for file in a.txt b.txt ./xxx/*.txt;do head -100 "$file";done
$ for file in *.txt; do sed -n 's/xxx/aaa/' "$file";done

, , , .

"-" ( ) :

./my_script -c "head -100" a.txt b.txt ./xxx/*.txt
./my_script -c "sed -n 's/xxx/aaa/'" *.txt

bash, getopts:

SCRIPT=$0

while getopts "c:" opt; do
    case $opt in
        c)
            command=$OPTARG
            ;;
    esac
done

shift $((OPTIND-1))

if [ -z "$command" ] || [ -z "$*" ]; then
    echo "Usage: $SCRIPT -c <command> file [file..]"
    exit
fi

, :

for target in "$@";do
     eval $command \"$target\"
done

STDIN, :

while read target; do
     eval $command \"$target\"
done
+6

$@, , , :

for parameter in "$@"
do
    echo "The parameter is '$parameter'"
done

:

head -100 test this "File name" out

the parameter is 'head'
the parameter is '-100'
the parameter is 'test'
the parameter is 'this'
the parameter is 'File name'
the parameter is 'out'

, , - . :

  • , :
  • , "-" "-", - .

, , :

if [[ "x${parameter}" == "x${parameter#-}" ]]

, . # . - , - glob ( ) . . , , . BTW, x . , , , .

:

parameterFlag=""
for parameter in "$@"     #Quotes are important!
do
    if [[ "x${parameter}" == "x${parameter#-}" ]]
    then
         parameterFlag="Tripped!"
    fi
    if [[ "x${parameter}" == "x--" ]]
    then
         print "Parameter \"$parameter\" ends the parameter list"
         parameterFlag="TRIPPED!"
    fi
    if [ -n $parameterFlag ]
    then
        print "\"$parameter\" is a file"
    else
        echo "The parameter \"$parameter\" is a parameter"
    fi
done
+3

1

, , , .

3

command=$1
shift
while [ $1 != '--' ]; do
    args="$args $1"
    shift
done
shift
while [ -n "$1" ]; do
    echo "$1"
    shift
done | $command $args

2

3?

0

All Articles