views:

363

answers:

6

I'm not entirely new to programming, but I'm not exactly experienced. I want to write small shell script for practice.

Here's what I have so far:

#!/bin/sh
name=$0
links=$3
owner=$4
if [ $# -ne 1 ]
then
        echo "Usage: $0 <directory>"
        exit 1
fi
if [ ! -e $1 ]
then
        echo "$1 not found"
        exit 1

elif [ -d $1 ]
then
        echo "Name\t\tLinks\t\tOwner\t\tDate"
        echo "$name\t$links\t$owner\t$date"
        exit 0
fi

Basically what I'm trying to do is have the script go through all of the files in a specified directory and then display the name of each file with the amount of links it has, its owner, and the date it was created. What would be the syntax for displaying the date of creation or at least the date of last modification of the file?

Another thing is, what is the syntax for creating a for loop? From what I understand I would have to write something like for $1 in $1 ($1 being all of the files in the directory the user typed in correct?) and then go through checking each file and displaying the information for each one. How would I start and end the for loop (what is the syntax for this?).

As you can see I'm not very familiar bourne shell programming. If you have any helpful websites or have a better way of approaching this please show me!

+1  A: 

You might want to look at Advanced Bash-Scripting Guide. It has a section that explains loops.

sigjuice
Thanks for the website it's very organized.
에이바
+4  A: 

Syntax for a for loop:

for var in list
do
    echo $var
done

for example:

for var in *
do
    echo $var
done

What you might want to consider however is something like this:

ls -l | while read perms links owner group size date1 date2 time filename
do
   echo $filename
done

which splits the output of ls -l into fields on-the-fly so you don't need to do any splitting yourself.

The field-splitting is controlled by the shell-variable IFS, which by default contains a space, tab and newline. If you change this in a shell script, remember to change it back. Thus by changing the value of IFS you can, for example, parse CSV files by setting this to a comma. this example reads three fields from a CSV and spits out the 2nd and 3rd only (it's effectively the shell equivalent of cut -d, -f2,3 inputfile.csv)

oldifs=$IFS
IFS=","
while read field1 field2 field3
do 
    echo $field2 $field3
done < inputfile.csv
IFS=oldifs

(note: you don't need to revert IFS, but I generally do to make sure that further text processing in a script isn't affected after I'm done with it).

Plenty of documentation out the on both for and while loops; just google for it :-)

Chris J
You have a redundant (and detrimental) dollar sign in your for loops. It should be `for var in *; do ... done`, without a `$` before the `var`.
ndim
Ah you're right a while loop would be more efficient. Thanks for the advice and syntax explanation.
에이바
@ndim -- good catch, fixed. I'd just come out of fiddling with perl for the past hour. I've got punctuation floating in front of my eyes... :-)
Chris J
@Chris J:Thanks for pointing out the splitting capability.
Alberto Zaccagni
+1  A: 

I suggest to use find with the option -printf "%P\t%n\t%u\t%t"

Aaron Digulla
A: 
for x in "$@"; do
    echo "$x"
done

The "$@" protects any whitespace in supplied file names. Obviously, do your real work in place of "echo $x", which isn't doing much. But $@ is all the junk supplied on the command line to your script.

But also, your script bails out if $# is not equal to 1, but you're apparently fully expecting up to 4 arguments (hence the $4 you reference in the early part of your script).

xcramps
A: 

assuming you have GNU find on your system

find /path -type f -printf "filename: %f | hardlinks: %n| owner: %u | time: %TH %Tb %TY\n"
ghostdog74
A: 

$1 is the first positional parameter, so $3 is the third and $4 is the fourth. They have nothing to do with the directory (or its files) the script was started from. If your script was started using this, for example:

./script.sh apple banana cherry date elderberry

then the variable $1 would equal "apple" and so on. The special parameter $# is the count of positional parameters, which in this case would be five.

The name of the script is contained in $0 and $* and $@ are arrays that contain all the positional parameters which behave differently depending on whether they appear in quotes.

You can refer to the positional parameters using a substring-style index:

${@:2:1}

would give "banana" using the example above. And:

${@: -1}

or

${@:$#}

would give the last ("elderberry"). Note that the space before the minus sign is required in this context.

Dennis Williamson