Reputation: 1824
I am using the following code to set up a variable containing a series of different file names, which I will then subsequently carry out some functions upon. The files involved are in a different directory (DIRECTORY
) to the directory where the code is being executed (CURRENT_DIRECTORY
). I thought the following code could be used to change into the directory containing the files cd $DIRECTORY
, store the list of files in the variable $FILES
and then change back to the original directory (cd $CURRENT_DIRECTORY
) where the rest of the code can be executed. However, if I do two echo commands, the first contains the file list when I am in the directory where the files are stored, but the second echo command just prints 'vclist_2d_*.txt'
, i.e. it interprets this as a string and not a list of files (presumably because I have changed back to the original directory and so it can't find any files that match vclist_2d_*.txt
). Why does this happen, and how can I get around this problem (without running everything in the same directory)?
#!/bin/bash
CURRENT_DIRECTORY=`pwd`
DIRECTORY=/home/Documents/NewDirectory/
cd $DIRECTORY
pwd
FILES=vclist_2d_*.txt
echo $FILES
cd $CURRENT_DIRECTORY
echo $FILES
Upvotes: 1
Views: 183
Reputation: 70223
FILES=vclist_2d_*.txt
does not get expanded by the shell. FILES
now contains the string vclist_2d_*.txt
.
echo $FILES
sends echo vclist_2d_*.txt
to the shell. The shell then expands the pattern, resulting in either A) the string vclist_2d_*.txt
if the pattern does not match anything, or B) a list of the matching file names.
You then change the directory, and repeat the process. At no point is the list of files assigned to any variable.
Now, you could assign the output of echo vclist_2d_*.txt
to a variable (SOMEVAR=$(echo vclist_2d_*.txt)
, but that would solve your problem only halfway. How do you intend to "act on each file in the list"? If you are thinking about a for file in $SOMEVAR
, consider what would happen if a filename contains a space...
The easiest, most robust solution to this is to use find
instead:
find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} +
This results in do_something
passed a list of matching files. If the list is very long, it may be split into multiple calls of do_something
.
find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} \;
This results in do_something
being called for each matching file.
If there is a chance that your current directory might contain files matching the pattern passed to find
above, you need to escape the asterisk (by adding quotes like I did, or escaping it via \*
) to avoid the shell expansion turning your find
command into something else.
Upvotes: 1
Reputation: 80921
You need to save the result of the glob expansion.
Globs are not expanded in simple variable assignments so your current code is expanding the glob when you echo
it (which is why you get the behavior you are seeing). Try echo "$FILES"
and it won't expand at all for example.
Assignment to arrays, however, do expand so FILES=(vclist_2d_*.txt)
will expand the glob immediately and then using echo "${FILES[@]}"
later will work correctly.
Upvotes: 4