I need to write a shell script that takes one or more arguments (filenames). Filenames should be handled corretly regardless of whether or not they contain spaces. For each file, the script should check if the file is readable, writeable, executable, is a plain file, and is a directory. For each of these checks, aa Y or N should be placed in the appropriate column. If the file does not exist, dashes "---" should be placed in each of the fields.
Example output:
Read Write Execute Plain Dir Filename
Y Y Y Y N /tmp/testfiles/executable
Y Y N Y N /tmp/testfiles/file with spaces
Y N N Y N /tmp/testfiles/justread
N Y N Y N /tmp/testfiles/justwrite
N N N Y N /tmp/testfiles/noperms
--- --- --- --- --- /tmp/testfiles/nosuchfile
Y Y N Y N /tmp/testfiles/readwrite
Y Y Y N Y /tmp/testfiles/somedir
I am not very familiar with UNIX shell scripts, but after reading through various articles online, I came up with the following solution.
#! /bin/sh
echo Read Write Execute Plain Dir Filename
argnum=0
while $argnum < $# do
FileExists $($argnum)
PrintFileName $($argnum)
done
function FileExists()
{
if test -e $1
then
IsReadable $1
IsWritable $1
IsExecutable $1
IsPlain $1
IsDir $1
else
echo --- --- --- --- ---
}
function IsReadable()
{
if test -r $1
then
echo Y
else
echo N
}
function IsWritable()
{
if test -w $1
then
echo Y
else
echo N
}
function IsExecutable()
{
if test -x $1
then
echo Y
else
echo N
}
function IsPlain()
{
if test -f $1
then
echo Y
else
echo N
}
function IsDirectory()
{
if test -d $($argnum)
then
echo Y
else
echo N
}
function PrintFilename()
{
echo $1
}
Unfortunately, script doesn't execute properly. I know there are problems (especially with the formatting), but I'm not sure how to fix them. Any help/suggestions you have would be very much appreciated.
Read Write Execute Plain Dir Filename ./script: line 7: syntax error near unexpected token done' ./script: line 7: done'
Its because, you need a ;
before do
.
Bash scans from top to down, and executes every line. So in the top few lines, Bash does not know about FileExists
and PrintFileName
. So what you'd need to do is put the declarations before calling them.
function FileExists
{
...
}
function IsReadable
{
...
}
// more functions..
//Iterate here and call the above functions.
Cleaner way of iterating:
for var in "$@"
do
FileExists $var
PrintFileName $var
done
You might have problems with formatting because echo spits out a newline; and you might just not get things in a single line. use printf
instead, and manually write out printf "\\n"
manually.
Also, @devnull points out, fi
is missing in every single instance of an if
block.
while "function Name () " syntax works, I prefer the style returned by declare -f Name
as my written form, since I use "declare -f name ..." to reproduce function bodies.
also, you might factor the "echo Y" and "echo N" from each function, simply returning the truth of the assertion. so, ...IsReadable, .. become:
IsReadable ()
{
test -r $1
}
and used
IsReadable $1 && echo Y || echo N
since I don't find the "&&" (AND) and the "||" (OR) syntax too noisy. Also, i prefer this
[[ -r $1 ]] && echo Y || echo N
So, my isreadable
:
isreadable () { [[ test -r $1 ]] ; }
since i allow one-line exceptions to the "declare -f" rule, and even have a function, fbdy
which does that: if the function body (less header, trailer) fits on one line, show it as a one-liner, otherwise, show it as the default.
Good to see you using functions. Keep it up. I mightily encourage their use.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.