开发者

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)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜