I got a recursive script which iterates a list of names, some of which are files and some are directories.
If it's a (non-empty) directory, I should call the script again with all of the files in the directory and check if they are legal.
The part of the code making the recursive call:
if [[ -d $var ]] ; then
if [ "$(ls -A $var)" ]; then
./validate `ls $var`
fi
fi
The part of code checking if the files are legal:
if [[ -f $var ]]; then
some code
fi
But, after making the recursive calls, I can no longer check any of the files inside that directory, because they are not in the same directory as the main script, the -f $var
if cannot see them.
Any suggestion how can I still see them and use them?
Why not use find ? Simple and easy solution to the problem.
Always quote variables, you never known when you will find a file or directory name with spaces
shopt -s nullglob
if [[ -d "$path" ]] ; then
contents=( "$path"/* )
if (( ${#contents[@]} > 0 )); then
"$0" "${contents[@]}"
fi
fi
find
var
is a lousy variable name $FUNCNAME
instead of "$0"
A few people have mentioned how find
might solve this problem, I just wanted to show how that might be done:
find /yourdirectory -type f -exec ./validate {} +;
This will find all regular files in yourdirectory
and recursively in all its sub-directories, and return their paths as arguments to ./validate
. The {}
is expanded to the paths of the files that find
locates within yourdirectory
. The +
at the end means that each call to validate will be on a large number of files, instead of calling it individually on each file (wherein the +
is replaced with a \\
), this provides a huge speedup sometimes.
One option is to change directory (carefully) into the sub-directory:
if [[ -d "$var" ]] ; then if [ "$(ls -A $var)" ]; then (cd "$var"; exec ./validate $(ls)) fi fi
The outer parentheses start a new shell so the cd
command does not affect the main shell. The exec
replaces the original shell with (a new copy of) the validate
script. Using $(...)
instead of back-ticks is sensible. In general, it is sensible to enclose variable names in double quotes when they refer to file names that might contain spaces (but see below). The $(ls)
will list the files in the directory.
Heaven help you with the ls
commands if any file names or directory names contain spaces; you should probably be using *
glob expansion instead. Note that a directory containing a single file with a name such as -n
would trigger a syntax error in your script.
As Jens noted in a comment, the location of the shell script ( validate
) has to be adjusted as you descend the directory hierarchy. The simplest mechanism is to have the script on your PATH, so you can write exec validate
or even exec $0
instead of exec ./validate
. Failing that, you need to adjust the value of $0
— assuming your shell leaves $0
as a relative path and doesn't mess around with converting it to an absolute path. So, a revised version of the code fragment might be:
# For validate on PATH or absolute name in $0
if [[ -d "$var" ]] ; then
if [ "$(ls -A $var)" ]; then
(cd "$var"; exec $0 $(ls))
fi
fi
or:
# For validate not on PATH and relative name in $0
if [[ -d "$var" ]] ; then
if [ "$(ls -A $var)" ]; then
(cd "$var"; exec ../$0 $(ls))
fi
fi
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.