Determining if a specific file exists within a shell script is straight-forward:
if [ -f filename.txt ]; then DoSomething; fi
The -f verifies that a regular file exists. You might want -s (exists and size is greater than zero), -w (exists and is writable), -e (a regular or special file exists), etc. But the test comes from the “CONDITIONAL EXPRESSIONS” section of the bash man page and is simply used in an if statement.
What if you don’t know the exact name of the file? Using the text “if [ -f *substring*.xtn ]” seems like it works. If there is no matching file, the condition evaluates to FALSE. If there is one matching file the condition evaluates to TRUE. But when there are multiple matching files, you get an error because there are too many parameters
[lisa@fc test]# ll total 0 [lisa@fc test]# if [ -f *something*.txt ]; then echo "The file exists"; fi [lisa@fc test]# touch 1something1.txt [lisa@fc test]# if [ -f *something*.txt ]; then echo "The file exists"; fi The file exists [lisa@fc test]# touch 2something2.txt [lisa@fc test]# if [ -f *something*.txt ]; then echo "The file exists"; fi -bash: [: 1something1.txt: binary operator expected
Beyond throwing an error … we are not executing the code-block meant to be run when the condition is TRUE. In a shell script, execution will continue past the block as if the condition evaluated to FALSE (i.e. the script does not just abnormally end on the error, making the failure more obvious).
To test for the existence of possibly multiple files matching a pattern, we can evaluate the number of files returned from ls. I include 2>/dev/null to hide the error which will otherwise be displayed when there are zero matching files.
[lisa@fc test]# ll total 0 [lisa@fc test]# if [ $(ls *something*.txt 2>/dev/null | wc -l) -gt 0 ]; then echo "Some matching files are found."; fi [lisa@fc test]# touch 1something1.txt [lisa@fc test]# if [ $(ls *something*.txt 2>/dev/null | wc -l) -gt 0 ]; then echo "Some matching files are found."; fi Some matching files are found. [lisa@fc test]# touch 2something2.txt [lisa@fc test]# if [ $(ls *something*.txt 2>/dev/null | wc -l) -gt 0 ]; then echo "Some matching files are found."; fi Some matching files are found. [lisa@fc test]#
Now we have a test that evaluates to TRUE when there are one or more matching files in the path.
.. every once in a while, even though you’ve been coding for years, you get into this hour or two frustration with “why doesn’t this work, tried XYZ, PDQ, etc.” – Googl’ing different methods for “if FILE_EXIST” to see if I was missing / had forgotten anything I hadn’t tried? I realized I’d gotten nailed by exactly the condition here, a multiple match. Maybe you went through the same pain.
Thanks *so* much for posting this.
Neat trick, nice one!
Thank you for detailed explanation