Well, "$@"
expands to the list of positional parameters, one argument per positional parameter.
When you do:
set '' 'foo bar' $'blah\nblah'
cmd "$@"
cmd
is being invoked with those 3 arguments: the empty string, foo bar
and blah<newline>blah
. The shell will call the execve()
system call with something like:
execve("/path/to/cmd", ["cmd", "", "foo bar", "blah\nblah"], [envvars...]);
If you want to reconstruct a shell command line (that is code in the shell language) that would reproduce that same invocation, you could do something like:
awk -v q="'" '
function shellquote(s) {
gsub(q, q "\\" q q, s)
return q s q
}
BEGIN {
for (i = 1; i < ARGC; i++) {
printf "%s", sep shellquote(ARGV[i])
sep = " "
}
printf "\n"
}' cmd "$@"
Or with zsh
, asking for different types of quotes:
$ set '' 'foo bar' $'blah\nblah'
$ print -r -- cmd "${(q)@}"
cmd '' foo\ bar blah$'\n'blah
$ print -r -- cmd "${(qq)@}"
cmd '' 'foo bar' 'blah
blah'
$ print -r -- cmd "${(qqq)@}"
cmd "" "foo bar" "blah
blah"
$ print -r -- cmd "${(qqqq)@}"
cmd $'' $'foo bar' $'blah\nblah'
Or with zsh
, bash
or ksh93
(here for bash
, YMMV with other shells):
$ set '' 'foo bar' $'blah\nblah'
$ printf cmd; printf ' %q' "$@"; printf '\n'
cmd '' foo\ bar $'blah\nblah'
You could also use the shell's xtrace option that causes the shell to print what it's going to execute:
$ (PS4=; set -x; : cmd "$@")
: cmd '' 'foo bar' 'blah
blah'
Above, we ran the :
no-op command with cmd
and the positional parameters as argument. My shell printed them in a nice quoted fashion suitable for reinput to the shell. Not all shells do that.
Conveniently, xargs -I
does exactly what you want:
$ xargs <my_file_list.txt -I filename ./my_command "filename"
-I replace-str
Replace occurrences of replace-str in the initial-arguments with names read
from standard input.
Also, unquoted blanks do not terminate input items;
instead the separator is the newline character.
Implies -x and -L 1.
This means it takes exactly one newline-delimited input line and invokes your command with it as a single argument. Nothing apart from newline is treated as a delimiter, so spaces and other special characters are fine.
Note that if you wanted to allow newlines in your filenames, the nul terminator (as per Wildcard's answer) will also work in a file.
Best Answer
You can check special variable $#:
Then, add an alias to your
~/.bashrc
;Now, each time you run
xyz
, the alias will be launched instead. This will call the script which checks whether you have any arguments and only launches the realxyz
command if you do. Obviously, change/usr/bin/xyz
to whatever the full path of the command is.