Reputation: 417
I use in a function a variable that was defined in another function, from the same script, but I receive an error.
testare()
{
find "$Home" -name "$({!i})"
rez=$?
test -d "$rez"
t1=$?
test -f "$rez"
t2=$?
if [ "$t1" -eq 0 ]
then
return 0
elif [ "$t2" -eq 0 ]
then
return 1
else
return 2
fi
}
menu ()
{
if [ "$#" -lt 2 ] || [ "$#" -gt 9 ]
then
echo "Error!"
return
fi
for (( i=2; i <= "$#"; ++i ))
do
testare "$({!i})"
rez=$?
if [ "$rez" -eq 0 ]
then
echo "Director with the same name exists!"
fi
if [ "$rez" -eq 1 ]
then
echo "File with the same name already exists!"
fi
if [ "$rez" -eq 2 ]
then
touch "$({!i})"
fi
done
}
menu $@
What my code should do: I call my script with maximum 9 parameters, the first one indicates the location where i must create files with the names of the other parameters. First i have to check if those names arent already present on my disc. The usage of FOR is mandatory.
The error shows up on the **** line, because of the i variable. I think " i " isnt available at that moment. How could I make this work? :(
I tried also with writing in another file the function and source it on menu, same result..
Upvotes: 1
Views: 179
Reputation: 2789
You can eliminate testare
and simply perform the script's function in one routine as follows:
#!/bin/bash
menu() {
if [ "$#" -lt 2 ] || [ "$#" -gt 9 ]; then
echo "Error!"
exit 1
fi
for (( i = 2; i <= "$#"; i++ )); do
if [ -d "$1/${!i}" ]; then
printf "Directory '%s' already exists! \n" "${!i}"
elif [ -f "$1/${!i}" ]; then
printf "File '%s' already exists! \n" "${!i}"
else
touch "$1/${!i}"
fi
done
exit 0
}
menu "$@"
But if you want to use the two routines as they are, then you can modify your script as follows:
testare() {
test -d "$1/$2"
t1="$?"
test -f "$1/$2"
t2="$?"
if [ "$t1" -eq 0 ]; then
return 0
elif [ "$t2" -eq 0 ]; then
return 1
else
return 2
fi
}
menu() {
if [ "$#" -lt 2 ] || [ "$#" -gt 9 ]; then
echo "Error!"
exit 1
fi
for (( i = 2; i <= "$#"; i++ )); do
testare "$1" "${!i}"
rez="$?"
if [ "$rez" -eq 0 ]; then
printf "Directory '%s' already exists! \n" "${!i}"
elif [ "$rez" -eq 1 ]; then
printf "File '%s' already exists! \n" "${!i}"
else
touch "$1/${!i}"
fi
done
exit 0
}
menu "$@"
Remember: when you are passing any variable as an argument, that parameter to the routine is accessed by $i
where i
is replaced by any number >=0
referring to the position of the argument from left to right.
For example, in your script, you had $({!i})
within testare
, but the variable i
is only defined in the menu
routine, hence using that variable in testare
results in errors. In order access the arguments passed to testare
, you should either directly access them, ie. $1
, $2
etc. or you should define a variable (in a loop, for example) and access them using that variable as ${!j}
for some variable j
.
Edit- explanation for first comment's questions:
Consider, for example, that you had an empty folder named dir
in your current working directory. Now you want to create files one
, two
and three
in the dir
folder. Hence, you pass it to your script as:
$ ./script dir one two three
Thus, "$1"=dir
, "$2"=one
etc. The line test -d "$1/$2"
tests whether $2
is a directory and exists within the $1
folder, ie. whether or not dir/one
exists and is a directory. This is necessary because all files need to be tested and created within the specified directory, which always comes as the first argument to the script (as you stated).
In your script, since testare
is doing the testing for existence of named file/directory, testare
will need access to the dir
directory, hence the reason for 2 arguments being passed to testare
in the line testare "$1" "${!i}"
, whereby the first argument is the dir
directory, and the second argument is the file to be tested.
As for your question on how many arguments a method should be called with, you should pass on as many arguments as needed to make the routine do what it is supposed to. For example, the routine testare
needed to have the dir
directory and some specified file, so that it can check whether that file exists within dir
. Hence calling testare dir somefile
by using testare "$1" "${!i}"
.
On the other hand, the %s
in printf
is a placeholder for "string", whose value is provided at the end. For example,
$ printf "This is not a placeholder for %s \n" "numbers"
This is not a placeholder for numbers
$ printf "The placeholder for numbers is %s \n" "%d"
The placeholder for numbers is %d
$ printf "pi as a whole number equals %d\n" 3
pi as a whole number equals 3
Edit 2: If you want to search the /home
directory recursively to check whether somefile
exists, you can do the following:
#!/bin/bash
file=$(find /home -name "somefile")
if [[ "$file" != "" ]]; then
echo "file exists"
else
echo "file does not exist"
fi
Upvotes: 2
Reputation: 15461
You can try this (comments and suggestions in the script) :
# Explicit function name
found() {
if [[ -f "$1" ]];then
foundtype="file"
# found() success, return 0
return 0
elif [[ -d "$1" ]]; then
foundtype="directory"
return 0
else
# found() failed, return 1
return 1
fi
}
menu () {
if [ $# -lt 2 ] || [ $# -gt 9 ]
then
# Explicit message sent to stderr
echo "Error : you must provide from 2 to 9 parameters" >&2
# exit script with 1 status code (failed)
exit 1
fi
destdir="$1"
shift
# loop over params
for file in "$@"
do
if found "$destdir/$file"; then # found value = found() return code
echo "$destdir/$file" "is an existing" "$foundtype";
continue; # next iteration
else
# create destination dir if doesn't exist (as dir or as file)
[ ! -d "$destdir" ] && [ ! -f "$destdir" ] && mkdir "$destdir"
echo "Creating $destdir/$file" && touch "$destdir/$file"
fi
done
}
menu "$@"
Upvotes: 2