Using $@ properly
I am trying to write a tiny script that accepts any number of command line arguments that prints out the rwx
permissions for a file (not directory)
What I have is
file=$@
if [ -f $file ] ; then
ls -开发者_开发百科l $file
fi
This accepts only one command line argument however. Thanks for any help.
Here is a demonstration of the some of the differences between $*
and $@
, with and without quotes:
#/bin/bash
for i in $*; do
echo "\$*: ..${i}.."
done; echo
for i in "$*"; do
echo "\"\$*\": ..${i}.."
done; echo
for i in $@; do
echo "\$@: ..${i}.."
done; echo
for i in "$@"; do
echo "\"\$@\": ..${i}.."
done; echo
Running it:
user@host$ ./paramtest abc "space here"
$*: ..abc..
$*: ..space..
$*: ..here..
"$*": ..abc space here..
$@: ..abc..
$@: ..space..
$@: ..here..
"$@": ..abc..
"$@": ..space here..
How about this one:
for file
do
test -f "$file" && ls -l "$file"
done
The for loop by default will work on $@, so you don't have to mention it. Note that you will need to quote "$file" in case if the file name has embedded space. For example, if you save your script to 'myll.sh':
$ myll.sh "My Report.txt" file1 file2
Then "My Report.txt" will be passed in as a whole token instead of 2 separate tokens: "My" and "Report.txt"
The variable you want is indeed $@
- this contains all command-line arguments as separate words, each passed on intact (no expansion). ($*
treats all of them as a single word - good luck sorting it out if you have spaces in filenames).
You can loop, if you like. This is easily expanded to more complex actions than ls
.
for file in "$@"; do
if [ -f "$file" ]; then
ls -l "$file"
fi
done
Note: you should quote $@
to protect any special characters inside! You should also quote $file
for the same reason - especially inside the test. If there is an empty string in $@
, file
will also be empty, and without quotes, -f will attempt to act on the ']'. Errors ensue.
Also, if all you need to do is ls
(skipping your if
) you can just do this:
ls -l "$@"
You could usefully loop over any files specified like this:
for file in "$@"; do
ls -l "$file"
done
If you want to double-check that the name specified is not a directory, you could do this:
for file in "$@"; do
if [ ! -d "$file" ]; then
ls -l "$file"
fi
done
the bash variable for all arguments passed to a script is "$*". Try:
for file in $*; do
if [ -f $file ] ; then
ls -l $file
fi
done
(not tested)
精彩评论