I would like to find some file types in pictures folder and I have created the following bash-script in /home/user/pictures
folder:
for i in *.pdf *.sh *.txt;
do
echo 'all file types with extension' $i;
find /home/user/pictures -type f -iname $i;
done
But when I execute the bash-script, it does not work as expected for files that are located on the base directory /home/user/pictures
. Instead of echo 'All File types with Extension *.sh' the command interprets the variable for base directory:
all file types with extension file1.sh
/home/user/pictures/file1.sh
all file types with extension file2.sh
/home/user/pictures/file2.sh
all file types with extension file3.sh
/home/user/pictures/file3.sh
I would like to know why echo - command does not print "All File types with Extension *.sh".
for i in '*.pdf' '*.sh' '*.txt'
do
echo "all file types with extension $i"
find /home/user/pictures -type f -iname "$i"
done
In bash, a string containing *
, or a variable which expands to such a string, may be expanded as a glob pattern unless that string is protected from glob expansion by putting it inside quotes (although if the glob pattern does not match any files, then the original glob pattern will remain after attempted expansion).
In this case, it is not wanted for the glob expansion to happen - the string containing the *
needs to be passed as a literal to each of the echo
and the find
commands. So the $i
should be enclosed in double quotes - these will allow the variable expansion from $i
, but the subsequent wildcard expansion will not occur. (If single quotes, i.e. '$i'
were used instead, then a literal $i
would be passed to echo
and to find
, which is not wanted either.)
In addition to this, the initial for
line needs to use quotes to protect against wildcard expansion in the event that any files matching any of the glob patterns exist in the current directory. Here, it does not matter whether single or double quotes are used.
Separately, the revised code here also removes some unnecessary semicolons. Semicolons in bash are a command separator and are not needed merely to terminate a statement (as in C etc).
What seems to be happening here is that one of the patterns used in the initial for
statement is matching files in the current directory (specifically the *.sh
is matching file1.sh
file2.sh
, and file3.sh
). It is therefore being replaced by a list of these filenames (file1.sh file2.sh file3.sh
) in the expression, and the for
statement will iterate over these values. (Note that the current directory might not be the same as either where the script is located or the top level directory used for the find
.)
It would also still be expected that the *.pdf
and *.txt
would be used in the expression -- either substituted or not, depending on whether any matches are found. Therefore the output shown in the question is probably not the whole output of the script.