Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Sometimes it is necessary to emulate and verify the above variables in small examples and then can be copied immediately to some script, etc.

I tried to solve by using a simple example in the following ways:

(find $1) /tmp
sh -c '(find $1) /tmp'
sh -c "find $1" /tmp
echo '(find $1) /tmp' | sh

and with other combinations. Also experimented by adding the shebang interpreter directive #!/bin/sh -x, but did not get the desired result.

Can I do this simply?

share|improve this question
    
(find $1) /tmp is a syntax error. Actually (any-command) more-arguments is a syntax error. Can you explain differently what you're trying to do? –  Celada Jul 4 at 15:20
1  
@Celada, it's not a syntax error in shells of the rc family (rc, es, akanga...), where in that case that's equivalent to find $1 /tmp. –  Stéphane Chazelas Jul 4 at 17:07

2 Answers 2

up vote 12 down vote accepted

The first argument after sh -c inline-script goes to $0 (which is also used for error messages), and the rest go in $1, $2...

$ sh -c 'blah; echo "$0"; echo "$1"' my-inline-script arg
my-inline-script: blah: command not found
my-inline-script
arg

So you want:

sh -c 'find "$1"' sh /tmp

(in the olden days, you could find sh implementations where the first arg went into $1 instead, so you would do:

sh -c 'find "$1"' /tmp /tmp

Or:

sh -c 'shift "$2"; find "$@"' sh 3 2 /tmp1 /tmp2

to account for both behaviours, but those shells are gone now that POSIX is prevalent and publicly available).


If you want to set $1, $2 in a local scope within the current shell, that's where you'd use functions. In Bourne-like shells:

my_func() {
  find "$1"
}
my_func /tmp

Some shells support anonymous functions. That's the case of zsh:

(){find "$1"} /tmp

Or es:

@{find $1} /tmp

To change the current positional parameters, permanently, the syntax is shell dependant. dchirikov has already covered the Bourne-like shells (Bourne, Korn, bash, zsh, POSIX, ash, yash...).

The syntax is:

set arg1 arg2 ... argn

However, you need:

set --

To empty that list and

set -- -foo

to set $1 to something starting with - or +, so it's a good habit to always use set -- especially when using arbitrary data such as set -- "$@" other-arg to add arguments to the end of the positional parameter list.

In shells of the csh family (csh, tcsh), you assign to the argv array:

set argv=(arg1 arg2)

In shells of the rc family (rc, es, akanga), to the * array:

*=(arg1 arg2)

Though you can also assign elements individually:

2=arg2

In fish, the positional parameters are in the argv array only (no $1, $@ there):

set argv arg1 arg2

In zsh, for compatibility with csh, you can also assign to the argv array:

argv=(arg1 arg2)
argv[4]=arg4

And you can also do:

5=arg5

That means you can also do things like:

argv+=(another-arg)

to add an argument to the end, and:

argv[-1]=()
argv[2]=()

to remove an argument from the end or the middle, which you can't easily do with other shells.

share|improve this answer
set --

is what you need:

$ set -- aaa bbb ccc
$ echo "$1"
aaa
$ echo "$2"
bbb
$ echo "$3"
ccc
$ echo "$@"
aaa bbb ccc
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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